home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / msdos / video.c < prev   
C/C++ Source or Header  |  2000-05-13  |  76KB  |  2,663 lines

  1. #include "mamalleg.h"
  2. #include "driver.h"
  3. #include <pc.h>
  4. #include <conio.h>
  5. #include <sys/farptr.h>
  6. #include <go32.h>
  7. #include "TwkUser.c"
  8. #include <math.h>
  9. #include "vgafreq.h"
  10. #include "vidhrdw/vector.h"
  11. #include "dirty.h"
  12. /*extra functions for 15.75KHz modes */
  13. #include "gen15khz.h"
  14. #include "ticker.h"
  15.  
  16.  
  17. /* function to make scanline mode */
  18. Register *make_scanline_mode(Register *inreg,int entries);
  19.  
  20. /*15.75KHz SVGA driver (req. for 15.75KHz Arcade Monitor Modes)*/
  21. SVGA15KHZDRIVER *SVGA15KHzdriver;
  22.  
  23.  
  24. /* from blit.c, for VGA triple buffering */
  25. extern int xpage_size;
  26. extern int no_xpages;
  27. void unchain_vga(Register *pReg);
  28.  
  29. static int warming_up;
  30.  
  31. /* tweak values for centering tweaked modes */
  32. int center_x;
  33. int center_y;
  34.  
  35. BEGIN_GFX_DRIVER_LIST
  36.     GFX_DRIVER_VGA
  37.     GFX_DRIVER_VESA3
  38.     GFX_DRIVER_VESA2L
  39.     GFX_DRIVER_VESA2B
  40.     GFX_DRIVER_VESA1
  41. END_GFX_DRIVER_LIST
  42.  
  43. BEGIN_COLOR_DEPTH_LIST
  44.     COLOR_DEPTH_8
  45.     COLOR_DEPTH_15
  46.     COLOR_DEPTH_16
  47. END_COLOR_DEPTH_LIST
  48.  
  49. #define BACKGROUND 0
  50.  
  51.  
  52. dirtygrid grid1;
  53. dirtygrid grid2;
  54. char *dirty_old=grid1;
  55. char *dirty_new=grid2;
  56.  
  57. void scale_vectorgames(int gfx_width,int gfx_height,int *width,int *height);
  58.  
  59. void center_mode(Register *pReg);
  60.  
  61. /* in msdos/sound.c */
  62. int msdos_update_audio(void);
  63.  
  64.  
  65.  
  66. /* specialized update_screen functions defined in blit.c */
  67.  
  68. /* dirty mode 1 (VIDEO_SUPPORTS_DIRTY) */
  69. void blitscreen_dirty1_vga(void);
  70. void blitscreen_dirty1_unchained_vga(void);
  71. void blitscreen_dirty1_vesa_1x_1x_8bpp(void);
  72. void blitscreen_dirty1_vesa_1x_2x_8bpp(void);
  73. void blitscreen_dirty1_vesa_1x_2xs_8bpp(void);
  74. void blitscreen_dirty1_vesa_2x_1x_8bpp(void);
  75. void blitscreen_dirty1_vesa_2x_2x_8bpp(void);
  76. void blitscreen_dirty1_vesa_2x_2xs_8bpp(void);
  77. void blitscreen_dirty1_vesa_2x_3x_8bpp(void);
  78. void blitscreen_dirty1_vesa_2x_3xs_8bpp(void);
  79. void blitscreen_dirty1_vesa_3x_1x_8bpp(void);
  80. void blitscreen_dirty1_vesa_3x_2x_8bpp(void);
  81. void blitscreen_dirty1_vesa_3x_2xs_8bpp(void);
  82. void blitscreen_dirty1_vesa_3x_3x_8bpp(void);
  83. void blitscreen_dirty1_vesa_3x_3xs_8bpp(void);
  84. void blitscreen_dirty1_vesa_4x_2x_8bpp(void);
  85. void blitscreen_dirty1_vesa_4x_2xs_8bpp(void);
  86. void blitscreen_dirty1_vesa_4x_3x_8bpp(void);
  87. void blitscreen_dirty1_vesa_4x_3xs_8bpp(void);
  88.  
  89. void blitscreen_dirty1_vesa_1x_1x_16bpp(void);
  90. void blitscreen_dirty1_vesa_1x_2x_16bpp(void);
  91. void blitscreen_dirty1_vesa_1x_2xs_16bpp(void);
  92. void blitscreen_dirty1_vesa_2x_1x_16bpp(void);
  93. void blitscreen_dirty1_vesa_2x_2x_16bpp(void);
  94. void blitscreen_dirty1_vesa_2x_2xs_16bpp(void);
  95. void blitscreen_dirty1_vesa_3x_1x_16bpp(void);
  96. void blitscreen_dirty1_vesa_3x_2x_16bpp(void);
  97. void blitscreen_dirty1_vesa_3x_2xs_16bpp(void);
  98. void blitscreen_dirty1_vesa_4x_2x_16bpp(void);
  99. void blitscreen_dirty1_vesa_4x_2xs_16bpp(void);
  100.  
  101. void blitscreen_dirty1_vesa_1x_1x_16bpp_palettized(void);
  102. void blitscreen_dirty1_vesa_1x_2x_16bpp_palettized(void);
  103. void blitscreen_dirty1_vesa_1x_2xs_16bpp_palettized(void);
  104. void blitscreen_dirty1_vesa_2x_1x_16bpp_palettized(void);
  105. void blitscreen_dirty1_vesa_2x_2x_16bpp_palettized(void);
  106. void blitscreen_dirty1_vesa_2x_2xs_16bpp_palettized(void);
  107. void blitscreen_dirty1_vesa_3x_1x_16bpp_palettized(void);
  108. void blitscreen_dirty1_vesa_3x_2x_16bpp_palettized(void);
  109. void blitscreen_dirty1_vesa_3x_2xs_16bpp_palettized(void);
  110. void blitscreen_dirty1_vesa_4x_2x_16bpp_palettized(void);
  111. void blitscreen_dirty1_vesa_4x_2xs_16bpp_palettized(void);
  112.  
  113.  
  114. /* dirty mode 0 (no osd_mark_dirty calls) */
  115. void blitscreen_dirty0_vga(void);
  116. void blitscreen_dirty0_unchained_vga(void);
  117. void blitscreen_dirty0_vesa_1x_1x_8bpp(void);
  118. void blitscreen_dirty0_vesa_1x_2x_8bpp(void);
  119. void blitscreen_dirty0_vesa_1x_2xs_8bpp(void);
  120. void blitscreen_dirty0_vesa_2x_1x_8bpp(void);
  121. void blitscreen_dirty0_vesa_2x_2x_8bpp(void);
  122. void blitscreen_dirty0_vesa_2x_2xs_8bpp(void);
  123. void blitscreen_dirty0_vesa_2x_3x_8bpp(void);
  124. void blitscreen_dirty0_vesa_2x_3xs_8bpp(void);
  125. void blitscreen_dirty0_vesa_3x_1x_8bpp(void);
  126. void blitscreen_dirty0_vesa_3x_2x_8bpp(void);
  127. void blitscreen_dirty0_vesa_3x_2xs_8bpp(void);
  128. void blitscreen_dirty0_vesa_3x_3x_8bpp(void);
  129. void blitscreen_dirty0_vesa_3x_3xs_8bpp(void);
  130. void blitscreen_dirty0_vesa_4x_2x_8bpp(void);
  131. void blitscreen_dirty0_vesa_4x_2xs_8bpp(void);
  132. void blitscreen_dirty0_vesa_4x_3x_8bpp(void);
  133. void blitscreen_dirty0_vesa_4x_3xs_8bpp(void);
  134.  
  135. void blitscreen_dirty0_vesa_1x_1x_16bpp(void);
  136. void blitscreen_dirty0_vesa_1x_2x_16bpp(void);
  137. void blitscreen_dirty0_vesa_1x_2xs_16bpp(void);
  138. void blitscreen_dirty0_vesa_2x_1x_16bpp(void);
  139. void blitscreen_dirty0_vesa_2x_2x_16bpp(void);
  140. void blitscreen_dirty0_vesa_2x_2xs_16bpp(void);
  141. void blitscreen_dirty0_vesa_3x_1x_16bpp(void);
  142. void blitscreen_dirty0_vesa_3x_2x_16bpp(void);
  143. void blitscreen_dirty0_vesa_3x_2xs_16bpp(void);
  144. void blitscreen_dirty0_vesa_4x_2x_16bpp(void);
  145. void blitscreen_dirty0_vesa_4x_2xs_16bpp(void);
  146.  
  147. void blitscreen_dirty0_vesa_1x_1x_16bpp_palettized(void);
  148. void blitscreen_dirty0_vesa_1x_2x_16bpp_palettized(void);
  149. void blitscreen_dirty0_vesa_1x_2xs_16bpp_palettized(void);
  150. void blitscreen_dirty0_vesa_2x_1x_16bpp_palettized(void);
  151. void blitscreen_dirty0_vesa_2x_2x_16bpp_palettized(void);
  152. void blitscreen_dirty0_vesa_2x_2xs_16bpp_palettized(void);
  153. void blitscreen_dirty0_vesa_3x_1x_16bpp_palettized(void);
  154. void blitscreen_dirty0_vesa_3x_2x_16bpp_palettized(void);
  155. void blitscreen_dirty0_vesa_3x_2xs_16bpp_palettized(void);
  156. void blitscreen_dirty0_vesa_4x_2x_16bpp_palettized(void);
  157. void blitscreen_dirty0_vesa_4x_2xs_16bpp_palettized(void);
  158.  
  159.  
  160.  
  161. static void update_screen_dummy(void);
  162. void (*update_screen)(void) = update_screen_dummy;
  163.  
  164. #define MAX_X_MULTIPLY 4
  165. #define MAX_Y_MULTIPLY 3
  166. #define MAX_X_MULTIPLY16 4
  167. #define MAX_Y_MULTIPLY16 2
  168.  
  169. static void (*updaters8[MAX_X_MULTIPLY][MAX_Y_MULTIPLY][2][2])(void) =
  170. {            /* 1 x 1 */
  171.     {    {    { blitscreen_dirty0_vesa_1x_1x_8bpp, blitscreen_dirty1_vesa_1x_1x_8bpp },
  172.             { blitscreen_dirty0_vesa_1x_1x_8bpp, blitscreen_dirty1_vesa_1x_1x_8bpp }
  173.         },    /* 1 x 2 */
  174.         {    { blitscreen_dirty0_vesa_1x_2x_8bpp,  blitscreen_dirty1_vesa_1x_2x_8bpp },
  175.             { blitscreen_dirty0_vesa_1x_2xs_8bpp, blitscreen_dirty1_vesa_1x_2xs_8bpp }
  176.         },    /* 1 x 3 */
  177.         {    { update_screen_dummy, update_screen_dummy },
  178.             { update_screen_dummy, update_screen_dummy },
  179.         }
  180.     },        /* 2 x 1 */
  181.     {    {    { blitscreen_dirty0_vesa_2x_1x_8bpp, blitscreen_dirty1_vesa_2x_1x_8bpp },
  182.             { blitscreen_dirty0_vesa_2x_1x_8bpp, blitscreen_dirty1_vesa_2x_1x_8bpp }
  183.         },    /* 2 x 2 */
  184.         {    { blitscreen_dirty0_vesa_2x_2x_8bpp,  blitscreen_dirty1_vesa_2x_2x_8bpp },
  185.             { blitscreen_dirty0_vesa_2x_2xs_8bpp, blitscreen_dirty1_vesa_2x_2xs_8bpp }
  186.         },    /* 2 x 3 */
  187.         {    { blitscreen_dirty0_vesa_2x_3x_8bpp,  blitscreen_dirty1_vesa_2x_3x_8bpp },
  188.             { blitscreen_dirty0_vesa_2x_3xs_8bpp, blitscreen_dirty1_vesa_2x_3xs_8bpp }
  189.         }
  190.     },        /* 3 x 1 */
  191.     {    {    { blitscreen_dirty0_vesa_3x_1x_8bpp,  blitscreen_dirty1_vesa_3x_1x_8bpp },
  192.             { update_screen_dummy, update_screen_dummy }
  193.         },    /* 3 x 2 */
  194.         {    { blitscreen_dirty0_vesa_3x_2x_8bpp,  blitscreen_dirty1_vesa_3x_2x_8bpp },
  195.             { blitscreen_dirty0_vesa_3x_2xs_8bpp, blitscreen_dirty1_vesa_3x_2xs_8bpp }
  196.         },    /* 3 x 3 */
  197.         {    { blitscreen_dirty0_vesa_3x_3x_8bpp,  blitscreen_dirty1_vesa_3x_3x_8bpp },
  198.             { blitscreen_dirty0_vesa_3x_3xs_8bpp, blitscreen_dirty1_vesa_3x_3xs_8bpp }
  199.         }
  200.     },        /* 4 x 1 */
  201.     {    {    { update_screen_dummy, update_screen_dummy },
  202.             { update_screen_dummy, update_screen_dummy }
  203.         },    /* 4 x 2 */
  204.         {    { blitscreen_dirty0_vesa_4x_2x_8bpp,  blitscreen_dirty1_vesa_4x_2x_8bpp },
  205.             { blitscreen_dirty0_vesa_4x_2xs_8bpp, blitscreen_dirty1_vesa_4x_2xs_8bpp }
  206.         },    /* 4 x 3 */
  207.         {    { blitscreen_dirty0_vesa_4x_3x_8bpp,  blitscreen_dirty1_vesa_4x_3x_8bpp },
  208.             { blitscreen_dirty0_vesa_4x_3xs_8bpp, blitscreen_dirty1_vesa_4x_3xs_8bpp }
  209.         }
  210.     }
  211. };
  212.  
  213. static void (*updaters16[MAX_X_MULTIPLY16][MAX_Y_MULTIPLY16][2][2])(void) =
  214. {                /* 1 x 1 */
  215.     {    {    { blitscreen_dirty0_vesa_1x_1x_16bpp, blitscreen_dirty1_vesa_1x_1x_16bpp },
  216.             { blitscreen_dirty0_vesa_1x_1x_16bpp, blitscreen_dirty1_vesa_1x_1x_16bpp }
  217.         },    /* 1 x 2 */
  218.         {    { blitscreen_dirty0_vesa_1x_2x_16bpp,  blitscreen_dirty1_vesa_1x_2x_16bpp },
  219.             { blitscreen_dirty0_vesa_1x_2xs_16bpp, blitscreen_dirty1_vesa_1x_2xs_16bpp }
  220.         }
  221.     },        /* 2 x 1 */
  222.     {    {    { blitscreen_dirty0_vesa_2x_1x_16bpp,  blitscreen_dirty1_vesa_2x_1x_16bpp },
  223.             { blitscreen_dirty0_vesa_2x_1x_16bpp,  blitscreen_dirty1_vesa_2x_1x_16bpp }
  224.         },    /* 2 x 2 */
  225.         {    { blitscreen_dirty0_vesa_2x_2x_16bpp,  blitscreen_dirty1_vesa_2x_2x_16bpp },
  226.             { blitscreen_dirty0_vesa_2x_2xs_16bpp, blitscreen_dirty1_vesa_2x_2xs_16bpp }
  227.         }
  228.     },        /* 3 x 1 */
  229.     {    {    { blitscreen_dirty0_vesa_3x_1x_16bpp, blitscreen_dirty1_vesa_3x_1x_16bpp },
  230.             { update_screen_dummy, update_screen_dummy }
  231.         },    /* 3 x 2 */
  232.         {    { blitscreen_dirty0_vesa_3x_2x_16bpp, blitscreen_dirty1_vesa_3x_2x_16bpp },
  233.             { blitscreen_dirty0_vesa_3x_2xs_16bpp, blitscreen_dirty1_vesa_3x_2xs_16bpp }
  234.         }
  235.     },        /* 4 x 1 */
  236.     {    {    { update_screen_dummy, update_screen_dummy },
  237.             { update_screen_dummy, update_screen_dummy }
  238.         },    /* 4 x 2 */
  239.         {    { blitscreen_dirty0_vesa_4x_2x_16bpp,  blitscreen_dirty1_vesa_4x_2x_16bpp },
  240.             { blitscreen_dirty0_vesa_4x_2xs_16bpp, blitscreen_dirty1_vesa_4x_2xs_16bpp }
  241.         }
  242.     }
  243.  
  244. };
  245.  
  246. static void (*updaters16_palettized[MAX_X_MULTIPLY16][MAX_Y_MULTIPLY16][2][2])(void) =
  247. {                /* 1 x 1 */
  248.     {    {    { blitscreen_dirty0_vesa_1x_1x_16bpp_palettized, blitscreen_dirty1_vesa_1x_1x_16bpp_palettized },
  249.             { blitscreen_dirty0_vesa_1x_1x_16bpp_palettized, blitscreen_dirty1_vesa_1x_1x_16bpp_palettized }
  250.         },    /* 1 x 2 */
  251.         {    { blitscreen_dirty0_vesa_1x_2x_16bpp_palettized,  blitscreen_dirty1_vesa_1x_2x_16bpp_palettized },
  252.             { blitscreen_dirty0_vesa_1x_2xs_16bpp_palettized, blitscreen_dirty1_vesa_1x_2xs_16bpp_palettized }
  253.         }
  254.     },        /* 2 x 1 */
  255.     {    {    { blitscreen_dirty0_vesa_2x_1x_16bpp_palettized,  blitscreen_dirty1_vesa_2x_1x_16bpp_palettized },
  256.             { blitscreen_dirty0_vesa_2x_1x_16bpp_palettized,  blitscreen_dirty1_vesa_2x_1x_16bpp_palettized }
  257.         },    /* 2 x 2 */
  258.         {    { blitscreen_dirty0_vesa_2x_2x_16bpp_palettized,  blitscreen_dirty1_vesa_2x_2x_16bpp_palettized },
  259.             { blitscreen_dirty0_vesa_2x_2xs_16bpp_palettized, blitscreen_dirty1_vesa_2x_2xs_16bpp_palettized }
  260.         }
  261.     },        /* 3 x 1 */
  262.     {    {    { blitscreen_dirty0_vesa_3x_1x_16bpp_palettized, blitscreen_dirty1_vesa_3x_1x_16bpp_palettized },
  263.             { update_screen_dummy, update_screen_dummy }
  264.         },    /* 3 x 2 */
  265.         {    { blitscreen_dirty0_vesa_3x_2x_16bpp_palettized, blitscreen_dirty1_vesa_3x_2x_16bpp_palettized },
  266.             { blitscreen_dirty0_vesa_3x_2xs_16bpp_palettized, blitscreen_dirty1_vesa_3x_2xs_16bpp_palettized }
  267.         }
  268.     },        /* 4 x 1 */
  269.     {    {    { update_screen_dummy, update_screen_dummy },
  270.             { update_screen_dummy, update_screen_dummy }
  271.         },    /* 4 x 2 */
  272.         {    { blitscreen_dirty0_vesa_4x_2x_16bpp_palettized,  blitscreen_dirty1_vesa_4x_2x_16bpp_palettized },
  273.             { blitscreen_dirty0_vesa_4x_2xs_16bpp_palettized, blitscreen_dirty1_vesa_4x_2xs_16bpp_palettized }
  274.         }
  275.     }
  276.  
  277. };
  278.  
  279. struct osd_bitmap *scrbitmap;
  280. static int modifiable_palette;
  281. static int screen_colors;
  282. static unsigned char *current_palette;
  283. static unsigned int *dirtycolor;
  284. static int dirtypalette;
  285. static int dirty_bright;
  286. static int bright_lookup[256];
  287. extern unsigned int doublepixel[256];
  288. extern unsigned int quadpixel[256]; /* for quadring pixels */
  289. extern UINT32 *palette_16bit_lookup;
  290.  
  291. int frameskip,autoframeskip;
  292. #define FRAMESKIP_LEVELS 12
  293.  
  294. /* type of monitor output- */
  295. /* Standard PC, NTSC, PAL or Arcade */
  296. int monitor_type;
  297.  
  298. int vgafreq;
  299. int always_synced;
  300. int video_sync;
  301. int wait_vsync;
  302. int use_triplebuf;
  303. int triplebuf_pos,triplebuf_page_width;
  304. int vsync_frame_rate;
  305. int skiplines;
  306. int skipcolumns;
  307. int scanlines;
  308. int stretch;
  309. int use_mmx;
  310. int mmxlfb;
  311. int use_tweaked;
  312. int use_vesa;
  313. int use_dirty;
  314. float osd_gamma_correction = 1.0;
  315. int brightness;
  316. float brightness_paused_adjust;
  317. char *resolution;
  318. char *mode_desc;
  319. int gfx_mode;
  320. int gfx_width;
  321. int gfx_height;
  322.  
  323.  
  324. /*new 'half' flag (req. for 15.75KHz Arcade Monitor Modes)*/
  325. int half_yres=0;
  326. /* indicates unchained video mode (req. for 15.75KHz Arcade Monitor Modes)*/
  327. int unchained;
  328. /* flags for lowscanrate modes */
  329. int scanrate15KHz;
  330.  
  331. static int auto_resolution;
  332. static int viswidth;
  333. static int visheight;
  334. static int skiplinesmax;
  335. static int skipcolumnsmax;
  336. static int skiplinesmin;
  337. static int skipcolumnsmin;
  338.  
  339. static int vector_game;
  340.  
  341. static Register *reg = 0;       /* for VGA modes */
  342. static int reglen = 0;  /* for VGA modes */
  343. static int videofreq;   /* for VGA modes */
  344.  
  345. int gfx_xoffset;
  346. int gfx_yoffset;
  347. int gfx_display_lines;
  348. int gfx_display_columns;
  349. static int xmultiply,ymultiply;
  350. int throttle = 1;       /* toggled by F10 */
  351.  
  352. static int gone_to_gfx_mode;
  353. static int frameskip_counter;
  354. static int frames_displayed;
  355. static TICKER start_time,end_time;    /* to calculate fps average on exit */
  356. #define FRAMES_TO_SKIP 20       /* skip the first few frames from the FPS calculation */
  357.                             /* to avoid counting the copyright and info screens */
  358.  
  359. unsigned char tw224x288_h, tw224x288_v;
  360. unsigned char tw240x256_h, tw240x256_v;
  361. unsigned char tw256x240_h, tw256x240_v;
  362. unsigned char tw256x256_h, tw256x256_v;
  363. unsigned char tw256x256_hor_h, tw256x256_hor_v;
  364. unsigned char tw288x224_h, tw288x224_v;
  365. unsigned char tw240x320_h, tw240x320_v;
  366. unsigned char tw320x240_h, tw320x240_v;
  367. unsigned char tw336x240_h, tw336x240_v;
  368. unsigned char tw384x224_h, tw384x224_v;
  369. unsigned char tw384x240_h, tw384x240_v;
  370. unsigned char tw384x256_h, tw384x256_v;
  371.  
  372.  
  373. struct vga_tweak { int x, y; Register *reg; int reglen; int syncvgafreq; int unchained; int vertical_mode; };
  374. struct vga_tweak vga_tweaked[] = {
  375.     { 240, 256, scr240x256, sizeof(scr240x256)/sizeof(Register),  1, 0, 1 },
  376.     { 256, 240, scr256x240, sizeof(scr256x240)/sizeof(Register),  0, 0, 0 },
  377.     { 256, 256, scr256x256, sizeof(scr256x256)/sizeof(Register),  1, 0, 1 },
  378.     { 256, 256, scr256x256hor, sizeof(scr256x256hor)/sizeof(Register),  0, 0, 0 },
  379.     { 224, 288, scr224x288, sizeof(scr224x288)/sizeof(Register),  1, 0, 1 },
  380.     { 288, 224, scr288x224, sizeof(scr288x224)/sizeof(Register),  0, 0, 0 },
  381.     { 240, 320, scr240x320, sizeof(scr240x320)/sizeof(Register),  1, 1, 1 },
  382.     { 320, 240, scr320x240, sizeof(scr320x240)/sizeof(Register),  0, 1, 0 },
  383.     { 336, 240, scr336x240, sizeof(scr336x240)/sizeof(Register),  0, 1, 0 },
  384.     { 384, 224, scr384x224, sizeof(scr384x224)/sizeof(Register),  1, 1, 0 },
  385.     { 384, 240, scr384x240, sizeof(scr384x240)/sizeof(Register),  1, 1, 0 },
  386.     { 384, 256, scr384x256, sizeof(scr384x256)/sizeof(Register),  1, 1, 0 },
  387.     { 0, 0 }
  388. };
  389. struct mode_adjust  {int x, y; unsigned char *hadjust; unsigned char *vadjust; int vertical_mode; };
  390.  
  391. /* horizontal and vertical total tweak values for above modes */
  392. struct mode_adjust  pc_adjust[] = {
  393.     { 240, 256, &tw240x256_h, &tw240x256_v, 1 },
  394.     { 256, 240, &tw256x240_h, &tw256x240_v, 0 },
  395.     { 256, 256, &tw256x256_hor_h, &tw256x256_hor_v, 0 },
  396.     { 256, 256, &tw256x256_h, &tw256x256_v, 1 },
  397.     { 224, 288, &tw224x288_h, &tw224x288_v, 1 },
  398.     { 288, 224, &tw288x224_h, &tw288x224_v, 0 },
  399.     { 240, 320, &tw240x320_h, &tw240x320_v, 1 },
  400.     { 320, 240, &tw320x240_h, &tw320x240_v, 0 },
  401.     { 336, 240, &tw336x240_h, &tw336x240_v, 0 },
  402.     { 384, 224, &tw384x224_h, &tw384x224_v, 0 },
  403.     { 384, 240, &tw384x240_h, &tw384x240_v, 0 },
  404.     { 384, 256, &tw384x256_h, &tw384x256_v, 0 },
  405.     { 0, 0 }
  406. };
  407.  
  408. /* Tweak values for arcade/ntsc/pal modes */
  409. unsigned char tw224x288arc_h, tw224x288arc_v, tw288x224arc_h, tw288x224arc_v;
  410. unsigned char tw256x240arc_h, tw256x240arc_v, tw256x256arc_h, tw256x256arc_v;
  411. unsigned char tw320x240arc_h, tw320x240arc_v, tw320x256arc_h, tw320x256arc_v;
  412. unsigned char tw352x240arc_h, tw352x240arc_v, tw352x256arc_h, tw352x256arc_v;
  413. unsigned char tw368x224arc_h, tw368x224arc_v;
  414. unsigned char tw368x240arc_h, tw368x240arc_v, tw368x256arc_h, tw368x256arc_v;
  415. unsigned char tw512x224arc_h, tw512x224arc_v, tw512x256arc_h, tw512x256arc_v;
  416. unsigned char tw512x448arc_h, tw512x448arc_v, tw512x512arc_h, tw512x512arc_v;
  417. unsigned char tw640x480arc_h, tw640x480arc_v;
  418.  
  419. /* 15.75KHz Modes */
  420. struct vga_15KHz_tweak { int x, y; Register *reg; int reglen;
  421.               int syncvgafreq; int vesa; int ntsc;
  422.               int half_yres; int matchx; };
  423. struct vga_15KHz_tweak arcade_tweaked[] = {
  424.     { 224, 288, scr224x288_15KHz, sizeof(scr224x288_15KHz)/sizeof(Register), 0, 0, 0, 0, 224 },
  425.     { 256, 240, scr256x240_15KHz, sizeof(scr256x240_15KHz)/sizeof(Register), 0, 0, 1, 0, 256 },
  426.     { 256, 256, scr256x256_15KHz, sizeof(scr256x256_15KHz)/sizeof(Register), 0, 0, 0, 0, 256 },
  427.     { 288, 224, scr288x224_15KHz, sizeof(scr288x224_15KHz)/sizeof(Register), 0, 0, 1, 0, 288 },
  428.     { 320, 240, scr320x240_15KHz, sizeof(scr320x240_15KHz)/sizeof(Register), 1, 0, 1, 0, 320 },
  429.     { 320, 256, scr320x256_15KHz, sizeof(scr320x256_15KHz)/sizeof(Register), 1, 0, 0, 0, 320 },
  430.     { 352, 240, scr352x240_15KHz, sizeof(scr352x240_15KHz)/sizeof(Register), 1, 0, 1, 0, 352 },
  431.     { 352, 256, scr352x256_15KHz, sizeof(scr352x256_15KHz)/sizeof(Register), 1, 0, 0, 0, 352 },
  432. /* force 384 games to match to 368 modes - the standard VGA clock speeds mean we can't go as wide as 384 */
  433.     { 368, 224, scr368x224_15KHz, sizeof(scr368x224_15KHz)/sizeof(Register), 1, 0, 1, 0, 384 },
  434. /* all VGA modes from now on are too big for triple buffering */
  435.     { 368, 240, scr368x240_15KHz, sizeof(scr368x240_15KHz)/sizeof(Register), 1, 0, 1, 0, 384 },
  436.     { 368, 256, scr368x256_15KHz, sizeof(scr368x256_15KHz)/sizeof(Register), 1, 0, 0, 0, 384 },
  437. /* double monitor modes */
  438.     { 512, 224, scr512x224_15KHz, sizeof(scr512x224_15KHz)/sizeof(Register), 0, 0, 1, 0, 512 },
  439.     { 512, 256, scr512x256_15KHz, sizeof(scr512x256_15KHz)/sizeof(Register), 0, 0, 0, 0, 512 },
  440. /* SVGA Mode (VGA register array not used) */
  441.     { 640, 480, NULL            , 0                                        , 0, 1, 1, 0, 640 },
  442. /* 'half y' VGA modes, used to fake hires if 'tweaked' is on */
  443.     { 512, 448, scr512x224_15KHz, sizeof(scr512x224_15KHz)/sizeof(Register), 0, 0, 1, 1, 512 },
  444.     { 512, 512, scr512x256_15KHz, sizeof(scr512x256_15KHz)/sizeof(Register), 0, 0, 0, 1, 512 },
  445.     { 0, 0 }
  446. };
  447.  
  448. /* horizontal and vertical total tweak values for above modes */
  449. struct mode_adjust  arcade_adjust[] = {
  450.     { 224, 288, &tw224x288arc_h, &tw224x288arc_v, 1 },
  451.     { 256, 240, &tw256x240arc_h, &tw256x240arc_v, 0 },
  452.     { 256, 256, &tw256x256arc_h, &tw256x256arc_v, 0 },
  453.     { 288, 224, &tw288x224arc_h, &tw288x224arc_v, 0 },
  454.     { 320, 240, &tw320x240arc_h, &tw320x240arc_v, 0 },
  455.     { 352, 240, &tw352x240arc_h, &tw352x240arc_v, 0 },
  456.     { 352, 256, &tw352x256arc_h, &tw352x256arc_v, 0 },
  457.     { 368, 224, &tw368x224arc_h, &tw368x224arc_v, 0 },
  458.     { 368, 240, &tw368x240arc_h, &tw368x240arc_v, 0 },
  459.     { 368, 256, &tw368x256arc_h, &tw368x256arc_v, 0 },
  460.     { 512, 224, &tw512x224arc_h, &tw512x224arc_v, 0 },
  461.     { 512, 256, &tw512x256arc_h, &tw512x256arc_v, 0 },
  462.     { 512, 448, &tw512x224arc_h, &tw512x224arc_v, 0 },
  463.     { 512, 512, &tw512x256arc_h, &tw512x256arc_v, 0 },
  464.     { 0, 0 }
  465. };
  466.  
  467. /* Create a bitmap. Also calls osd_clearbitmap() to appropriately initialize */
  468. /* it to the background color. */
  469. /* VERY IMPORTANT: the function must allocate also a "safety area" 16 pixels wide all */
  470. /* around the bitmap. This is required because, for performance reasons, some graphic */
  471. /* routines don't clip at boundaries of the bitmap. */
  472.  
  473. const int safety = 16;
  474.  
  475. struct osd_bitmap *osd_new_bitmap(int width,int height,int depth)       /* ASG 980209 */
  476. {
  477.     struct osd_bitmap *bitmap;
  478.  
  479.  
  480.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  481.     {
  482.         int temp;
  483.  
  484.         temp = width;
  485.         width = height;
  486.         height = temp;
  487.     }
  488.  
  489.     if ((bitmap = malloc(sizeof(struct osd_bitmap))) != 0)
  490.     {
  491.         int i,rowlen,rdwidth;
  492.         unsigned char *bm;
  493.  
  494.  
  495.         if (depth != 8 && depth != 16) depth = 8;
  496.  
  497.         bitmap->depth = depth;
  498.         bitmap->width = width;
  499.         bitmap->height = height;
  500.  
  501.         rdwidth = (width + 7) & ~7;     /* round width to a quadword */
  502.         if (depth == 16)
  503.             rowlen = 2 * (rdwidth + 2 * safety) * sizeof(unsigned char);
  504.         else
  505.             rowlen =     (rdwidth + 2 * safety) * sizeof(unsigned char);
  506.  
  507.         if ((bm = malloc((height + 2 * safety) * rowlen)) == 0)
  508.         {
  509.             free(bitmap);
  510.             return 0;
  511.         }
  512.  
  513.         /* clear ALL bitmap, including safety area, to avoid garbage on right */
  514.         /* side of screen is width is not a multiple of 4 */
  515.         memset(bm,0,(height + 2 * safety) * rowlen);
  516.  
  517.         if ((bitmap->line = malloc((height + 2 * safety) * sizeof(unsigned char *))) == 0)
  518.         {
  519.             free(bm);
  520.             free(bitmap);
  521.             return 0;
  522.         }
  523.  
  524.         for (i = 0;i < height + 2 * safety;i++)
  525.         {
  526.             if (depth == 16)
  527.                 bitmap->line[i] = &bm[i * rowlen + 2*safety];
  528.             else
  529.                 bitmap->line[i] = &bm[i * rowlen + safety];
  530.         }
  531.         bitmap->line += safety;
  532.  
  533.         bitmap->_private = bm;
  534.  
  535.         osd_clearbitmap(bitmap);
  536.     }
  537.  
  538.     return bitmap;
  539. }
  540.  
  541.  
  542.  
  543. /* set the bitmap to black */
  544. void osd_clearbitmap(struct osd_bitmap *bitmap)
  545. {
  546.     int i;
  547.  
  548.  
  549.     for (i = 0;i < bitmap->height;i++)
  550.     {
  551.         if (bitmap->depth == 16)
  552.             memset(bitmap->line[i],0,2*bitmap->width);
  553.         else
  554.             memset(bitmap->line[i],BACKGROUND,bitmap->width);
  555.     }
  556.  
  557.  
  558.     if (bitmap == scrbitmap)
  559.     {
  560.         extern int bitmap_dirty;        /* in mame.c */
  561.  
  562.         osd_mark_dirty (0,0,bitmap->width-1,bitmap->height-1,1);
  563.         bitmap_dirty = 1;
  564.     }
  565. }
  566.  
  567.  
  568.  
  569. void osd_free_bitmap(struct osd_bitmap *bitmap)
  570. {
  571.     if (bitmap)
  572.     {
  573.         bitmap->line -= safety;
  574.         free(bitmap->line);
  575.         free(bitmap->_private);
  576.         free(bitmap);
  577.     }
  578. }
  579.  
  580.  
  581. void osd_mark_dirty(int _x1, int _y1, int _x2, int _y2, int ui)
  582. {
  583.     if (use_dirty)
  584.     {
  585.         int x, y;
  586.  
  587. //        logerror("mark_dirty %3d,%3d - %3d,%3d\n", _x1,_y1, _x2,_y2);
  588.  
  589.         _x1 -= skipcolumns;
  590.         _x2 -= skipcolumns;
  591.         _y1 -= skiplines;
  592.         _y2 -= skiplines;
  593.  
  594.     if (_y1 >= gfx_display_lines || _y2 < 0 || _x1 > gfx_display_columns || _x2 < 0) return;
  595.         if (_y1 < 0) _y1 = 0;
  596.         if (_y2 >= gfx_display_lines) _y2 = gfx_display_lines - 1;
  597.         if (_x1 < 0) _x1 = 0;
  598.         if (_x2 >= gfx_display_columns) _x2 = gfx_display_columns - 1;
  599.  
  600.         for (y = _y1; y <= _y2 + 15; y += 16)
  601.             for (x = _x1; x <= _x2 + 15; x += 16)
  602.                 MARKDIRTY(x,y);
  603.     }
  604. }
  605.  
  606. static void init_dirty(char dirty)
  607. {
  608.     memset(dirty_new, dirty, MAX_GFX_WIDTH/16 * MAX_GFX_HEIGHT/16);
  609. }
  610.  
  611. INLINE void swap_dirty(void)
  612. {
  613.     char *tmp;
  614.  
  615.     tmp = dirty_old;
  616.     dirty_old = dirty_new;
  617.     dirty_new = tmp;
  618. }
  619.  
  620. /*
  621.  * This function tries to find the best display mode.
  622.  */
  623. static void select_display_mode(int depth)
  624. {
  625.     int width,height, i;
  626.  
  627.     auto_resolution = 0;
  628.     /* assume unchained video mode  */
  629.     unchained = 0;
  630.     /* see if it's a low scanrate mode */
  631.     switch (monitor_type)
  632.     {
  633.         case MONITOR_TYPE_NTSC:
  634.         case MONITOR_TYPE_PAL:
  635.         case MONITOR_TYPE_ARCADE:
  636.             scanrate15KHz = 1;
  637.             break;
  638.         default:
  639.             scanrate15KHz = 0;
  640.     }
  641.  
  642.     /* initialise quadring table [useful for *all* doubling modes */
  643.     for (i = 0; i < 256; i++)
  644.     {
  645.         doublepixel[i] = i | (i<<8);
  646.         quadpixel[i] = i | (i<<8) | (i << 16) | (i << 24);
  647.     }
  648.  
  649.     if (vector_game)
  650.     {
  651.         width = Machine->drv->screen_width;
  652.         height = Machine->drv->screen_height;
  653.     }
  654.     else
  655.     {
  656.         width = Machine->drv->visible_area.max_x - Machine->drv->visible_area.min_x + 1;
  657.         height = Machine->drv->visible_area.max_y - Machine->drv->visible_area.min_y + 1;
  658.     }
  659.  
  660.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  661.     {
  662.         int temp;
  663.  
  664.         temp = width;
  665.         width = height;
  666.         height = temp;
  667.     }
  668.  
  669.     use_vesa = -1;
  670.  
  671.     /* 16 bit color is supported only by VESA modes */
  672.     if (depth == 16)
  673.     {
  674.         logerror("Game needs 16-bit colors. Using VESA\n");
  675.         use_tweaked = 0;
  676.         /* only one 15.75KHz VESA mode, so force that */
  677.         if (scanrate15KHz == 1)
  678.         {
  679.             gfx_width = 640;
  680.             gfx_height = 480;
  681.         }
  682.     }
  683.  
  684.  
  685.   /* Check for special 15.75KHz mode (req. for 15.75KHz Arcade Modes) */
  686.     if (scanrate15KHz == 1)
  687.     {
  688.         switch (monitor_type)
  689.         {
  690.             case MONITOR_TYPE_NTSC:
  691.                 logerror("Using special NTSC video mode.\n");
  692.                 break;
  693.             case MONITOR_TYPE_PAL:
  694.                 logerror("Using special PAL video mode.\n");
  695.                 break;
  696.             case MONITOR_TYPE_ARCADE:
  697.                 logerror("Using special arcade monitor mode.\n");
  698.                 break;
  699.         }
  700.         scanlines = 0;
  701.         /* if no width/height specified, pick one from our tweaked list */
  702.         if (!gfx_width && !gfx_height)
  703.         {
  704.             for (i=0; arcade_tweaked[i].x != 0; i++)
  705.             {
  706.                 /* find height/width fit */
  707.                 /* only allow VESA modes if vesa explicitly selected */
  708.                 /* only allow PAL / NTSC modes if explicitly selected */
  709.                 /* arcade modes cover 50-60Hz) */
  710.                 if ((use_tweaked == 0 ||!arcade_tweaked[i].vesa) &&
  711.                     (monitor_type == MONITOR_TYPE_ARCADE || /* handles all 15.75KHz modes */
  712.                     (arcade_tweaked[i].ntsc && monitor_type == MONITOR_TYPE_NTSC) ||  /* NTSC only */
  713.                     (!arcade_tweaked[i].ntsc && monitor_type == MONITOR_TYPE_PAL)) &&  /* PAL ONLY */
  714.                     width  <= arcade_tweaked[i].matchx &&
  715.                     height <= arcade_tweaked[i].y)
  716.  
  717.                 {
  718.                     gfx_width  = arcade_tweaked[i].x;
  719.                     gfx_height = arcade_tweaked[i].y;
  720.                     break;
  721.                 }
  722.             }
  723.             /* if it's a vector, and there's isn't an SVGA support we want to avoid the half modes */
  724.             /* - so force default res. */
  725.             if (vector_game && (use_vesa == 0 || monitor_type == MONITOR_TYPE_PAL))
  726.                 gfx_width = 0;
  727.  
  728.             /* we didn't find a tweaked 15.75KHz mode to fit */
  729.             if (gfx_width == 0)
  730.             {
  731.                 /* pick a default resolution for the monitor type */
  732.                 /* something with the right refresh rate + an aspect ratio which can handle vectors */
  733.                 switch (monitor_type)
  734.                 {
  735.                     case MONITOR_TYPE_NTSC:
  736.                     case MONITOR_TYPE_ARCADE:
  737.                         gfx_width = 320; gfx_height = 240;
  738.                         break;
  739.                     case MONITOR_TYPE_PAL:
  740.                         gfx_width = 320; gfx_height = 256;
  741.                         break;
  742.                 }
  743.  
  744.                 use_vesa = 0;
  745.             }
  746.             else
  747.                 use_vesa = arcade_tweaked[i].vesa;
  748.         }
  749.  
  750.     }
  751.  
  752.  
  753.     /* If using tweaked modes, check if there exists one to fit
  754.        the screen in, otherwise use VESA */
  755.     if (use_tweaked && !gfx_width && !gfx_height)
  756.     {
  757.         for (i=0; vga_tweaked[i].x != 0; i++)
  758.         {
  759.             if (width <= vga_tweaked[i].x &&
  760.                 height <= vga_tweaked[i].y)
  761.             {
  762.                 /*check for 57Hz modes which would fit into a 60Hz mode*/
  763.                 if (gfx_width <= 256 && gfx_height <= 256 &&
  764.                     video_sync && Machine->drv->frames_per_second == 57)
  765.                 {
  766.                     gfx_width = 256;
  767.                     gfx_height = 256;
  768.                     use_vesa = 0;
  769.                     break;
  770.                 }
  771.  
  772.                 /* check for correct horizontal/vertical modes */
  773.                 if((!vga_tweaked[i].vertical_mode && !(Machine->orientation & ORIENTATION_SWAP_XY)) ||
  774.                     (vga_tweaked[i].vertical_mode && (Machine->orientation & ORIENTATION_SWAP_XY)))
  775.                 {
  776.                     gfx_width  = vga_tweaked[i].x;
  777.                     gfx_height = vga_tweaked[i].y;
  778.                     use_vesa = 0;
  779.                     /* leave the loop on match */
  780.  
  781. if (gfx_width == 320 && gfx_height == 240 && scanlines == 0)
  782. {
  783.     use_vesa = 1;
  784.     gfx_width = 0;
  785.     gfx_height = 0;
  786. }
  787.                     break;
  788.                 }
  789.             }
  790.         }
  791.         /* If we didn't find a tweaked VGA mode, use VESA */
  792.         if (gfx_width == 0)
  793.         {
  794.             logerror("Did not find a tweaked VGA mode. Using VESA.\n");
  795.             use_vesa = 1;
  796.         }
  797.     }
  798.  
  799.  
  800.     /* If no VESA resolution has been given, we choose a sensible one. */
  801.     /* 640x480, 800x600 and 1024x768 are common to all VESA drivers. */
  802.     if (!gfx_width && !gfx_height)
  803.     {
  804.         auto_resolution = 1;
  805.         use_vesa = 1;
  806.  
  807.         /* vector games use 640x480 as default */
  808.         if (vector_game)
  809.         {
  810.             gfx_width = 640;
  811.             gfx_height = 480;
  812.         }
  813.         else
  814.         {
  815.             int xm,ym;
  816.  
  817.             xm = ym = 1;
  818.  
  819.             if ((Machine->drv->video_attributes & VIDEO_PIXEL_ASPECT_RATIO_MASK)
  820.                     == VIDEO_PIXEL_ASPECT_RATIO_1_2)
  821.             {
  822.                 if (Machine->orientation & ORIENTATION_SWAP_XY)
  823.                     xm++;
  824.                 else ym++;
  825.             }
  826.  
  827.             if (scanlines && stretch)
  828.             {
  829.                 if (ym == 1)
  830.                 {
  831.                     xm *= 2;
  832.                     ym *= 2;
  833.                 }
  834.  
  835.                 /* see if pixel doubling can be applied at 640x480 */
  836.                 if (ym*height <= 480 && xm*width <= 640 &&
  837.                         (xm > 1 || (ym+1)*height > 768 || (xm+1)*width > 1024))
  838.                 {
  839.                     gfx_width = 640;
  840.                     gfx_height = 480;
  841.                 }
  842.                 /* see if pixel doubling can be applied at 800x600 */
  843.                 else if (ym*height <= 600 && xm*width <= 800 &&
  844.                         (xm > 1 || (ym+1)*height > 768 || (xm+1)*width > 1024))
  845.                 {
  846.                     gfx_width = 800;
  847.                     gfx_height = 600;
  848.                 }
  849.                 /* don't use 1024x768 right away. If 512x384 is available, it */
  850.                 /* will provide hardware scanlines. */
  851.  
  852.                 if (ym > 1 && xm > 1)
  853.                 {
  854.                     xm /= 2;
  855.                     ym /= 2;
  856.                 }
  857.             }
  858.  
  859.             if (!gfx_width && !gfx_height)
  860.             {
  861.                 if (ym*height <= 240 && xm*width <= 320)
  862.                 {
  863.                     gfx_width = 320;
  864.                     gfx_height = 240;
  865.                 }
  866.                 else if (ym*height <= 300 && xm*width <= 400)
  867.                 {
  868.                     gfx_width = 400;
  869.                     gfx_height = 300;
  870.                 }
  871.                 else if (ym*height <= 384 && xm*width <= 512)
  872.                 {
  873.                     gfx_width = 512;
  874.                     gfx_height = 384;
  875.                 }
  876.                 else if (ym*height <= 480 && xm*width <= 640 &&
  877.                         (!stretch || (ym+1)*height > 768 || (xm+1)*width > 1024))
  878.                 {
  879.                     gfx_width = 640;
  880.                     gfx_height = 480;
  881.                 }
  882.                 else if (ym*height <= 600 && xm*width <= 800 &&
  883.                         (!stretch || (ym+1)*height > 768 || (xm+1)*width > 1024))
  884.                 {
  885.                     gfx_width = 800;
  886.                     gfx_height = 600;
  887.                 }
  888.                 else
  889.                 {
  890.                     gfx_width = 1024;
  891.                     gfx_height = 768;
  892.                 }
  893.             }
  894.         }
  895.     }
  896. }
  897.  
  898.  
  899.  
  900. /* center image inside the display based on the visual area */
  901. static void adjust_display(int xmin, int ymin, int xmax, int ymax, int depth)
  902. {
  903.     int temp;
  904.     int w,h;
  905.     int act_width;
  906.  
  907. /* if it's a SVGA arcade monitor mode, get the memory width of the mode */
  908. /* this could be double the width of the actual mode set */
  909.     if (scanrate15KHz && SVGA15KHzdriver && use_vesa == 1)
  910.         act_width = SVGA15KHzdriver->getlogicalwidth (gfx_width);
  911.     else
  912.         act_width = gfx_width;
  913.  
  914.  
  915.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  916.     {
  917.         temp = xmin; xmin = ymin; ymin = temp;
  918.         temp = xmax; xmax = ymax; ymax = temp;
  919.         w = Machine->drv->screen_height;
  920.         h = Machine->drv->screen_width;
  921.     }
  922.     else
  923.     {
  924.         w = Machine->drv->screen_width;
  925.         h = Machine->drv->screen_height;
  926.     }
  927.  
  928.     if (!vector_game)
  929.     {
  930.         if (Machine->orientation & ORIENTATION_FLIP_X)
  931.         {
  932.             temp = w - xmin - 1;
  933.             xmin = w - xmax - 1;
  934.             xmax = temp;
  935.         }
  936.         if (Machine->orientation & ORIENTATION_FLIP_Y)
  937.         {
  938.             temp = h - ymin - 1;
  939.             ymin = h - ymax - 1;
  940.             ymax = temp;
  941.         }
  942.     }
  943.  
  944.     viswidth  = xmax - xmin + 1;
  945.     visheight = ymax - ymin + 1;
  946.  
  947.  
  948.     /* setup xmultiply to handle SVGA driver's (possible) double width */
  949.     xmultiply = act_width / gfx_width;
  950.     ymultiply = 1;
  951.  
  952.     if (use_vesa && !vector_game)
  953.     {
  954.         if (stretch)
  955.         {
  956.             if (!(Machine->orientation & ORIENTATION_SWAP_XY) &&
  957.                     !(Machine->drv->video_attributes & VIDEO_DUAL_MONITOR))
  958.             {
  959.                 /* horizontal, non dual monitor games may be stretched at will */
  960.                 while ((xmultiply+1) * viswidth <= act_width)
  961.                     xmultiply++;
  962.                 while ((ymultiply+1) * visheight <= gfx_height)
  963.                     ymultiply++;
  964.             }
  965.             else
  966.             {
  967.                 int tw,th;
  968.  
  969.                 tw = act_width;
  970.                 th = gfx_height;
  971.  
  972.                 if ((Machine->drv->video_attributes & VIDEO_PIXEL_ASPECT_RATIO_MASK)
  973.                         == VIDEO_PIXEL_ASPECT_RATIO_1_2)
  974.                 {
  975.                     if (Machine->orientation & ORIENTATION_SWAP_XY)
  976.                         tw /= 2;
  977.                     else th /= 2;
  978.                 }
  979.  
  980.                 /* Hack for 320x480 and 400x600 "vmame" video modes */
  981.                 if ((gfx_width == 320 && gfx_height == 480) ||
  982.                         (gfx_width == 400 && gfx_height == 600))
  983.                     th /= 2;
  984.  
  985.                 /* maintain aspect ratio for other games */
  986.                 while ((xmultiply+1) * viswidth <= tw &&
  987.                         (ymultiply+1) * visheight <= th)
  988.                 {
  989.                     xmultiply++;
  990.                     ymultiply++;
  991.                 }
  992.  
  993.                 if ((Machine->drv->video_attributes & VIDEO_PIXEL_ASPECT_RATIO_MASK)
  994.                         == VIDEO_PIXEL_ASPECT_RATIO_1_2)
  995.                 {
  996.                     if (Machine->orientation & ORIENTATION_SWAP_XY)
  997.                         xmultiply *= 2;
  998.                     else ymultiply *= 2;
  999.                 }
  1000.  
  1001.                 /* Hack for 320x480 and 400x600 "vmame" video modes */
  1002.                 if ((gfx_width == 320 && gfx_height == 480) ||
  1003.                         (gfx_width == 400 && gfx_height == 600))
  1004.                     ymultiply *= 2;
  1005.             }
  1006.         }
  1007.         else
  1008.         {
  1009.             if ((Machine->drv->video_attributes & VIDEO_PIXEL_ASPECT_RATIO_MASK)
  1010.                     == VIDEO_PIXEL_ASPECT_RATIO_1_2)
  1011.             {
  1012.                 if (Machine->orientation & ORIENTATION_SWAP_XY)
  1013.                     xmultiply *= 2;
  1014.                 else ymultiply *= 2;
  1015.             }
  1016.  
  1017.             /* Hack for 320x480 and 400x600 "vmame" video modes */
  1018.             if ((gfx_width == 320 && gfx_height == 480) ||
  1019.                     (gfx_width == 400 && gfx_height == 600))
  1020.                 ymultiply *= 2;
  1021.         }
  1022.     }
  1023.  
  1024.     if (depth == 16)
  1025.     {
  1026.         if (xmultiply > MAX_X_MULTIPLY16) xmultiply = MAX_X_MULTIPLY16;
  1027.         if (ymultiply > MAX_Y_MULTIPLY16) ymultiply = MAX_Y_MULTIPLY16;
  1028.     }
  1029.     else
  1030.     {
  1031.         if (xmultiply > MAX_X_MULTIPLY) xmultiply = MAX_X_MULTIPLY;
  1032.         if (ymultiply > MAX_Y_MULTIPLY) ymultiply = MAX_Y_MULTIPLY;
  1033.     }
  1034.  
  1035.     gfx_display_lines = visheight;
  1036.     gfx_display_columns = viswidth;
  1037.  
  1038.     gfx_xoffset = (act_width - viswidth * xmultiply) / 2;
  1039.     if (gfx_display_columns > act_width / xmultiply)
  1040.         gfx_display_columns = act_width / xmultiply;
  1041.  
  1042.     gfx_yoffset = (gfx_height - visheight * ymultiply) / 2;
  1043.         if (gfx_display_lines > gfx_height / ymultiply)
  1044.             gfx_display_lines = gfx_height / ymultiply;
  1045.  
  1046.  
  1047.     skiplinesmin = ymin;
  1048.     skiplinesmax = visheight - gfx_display_lines + ymin;
  1049.     skipcolumnsmin = xmin;
  1050.     skipcolumnsmax = viswidth - gfx_display_columns + xmin;
  1051.  
  1052.     /* Align on a quadword !*/
  1053.     gfx_xoffset &= ~7;
  1054.  
  1055.     /* the skipcolumns from mame.cfg/cmdline is relative to the visible area */
  1056.     skipcolumns = xmin + skipcolumns;
  1057.     skiplines   = ymin + skiplines;
  1058.  
  1059.     /* Just in case the visual area doesn't fit */
  1060.     if (gfx_xoffset < 0)
  1061.     {
  1062.         skipcolumns -= gfx_xoffset;
  1063.         gfx_xoffset = 0;
  1064.     }
  1065.     if (gfx_yoffset < 0)
  1066.     {
  1067.         skiplines   -= gfx_yoffset;
  1068.         gfx_yoffset = 0;
  1069.     }
  1070.  
  1071.     /* Failsafe against silly parameters */
  1072.     if (skiplines < skiplinesmin)
  1073.         skiplines = skiplinesmin;
  1074.     if (skipcolumns < skipcolumnsmin)
  1075.         skipcolumns = skipcolumnsmin;
  1076.     if (skiplines > skiplinesmax)
  1077.         skiplines = skiplinesmax;
  1078.     if (skipcolumns > skipcolumnsmax)
  1079.         skipcolumns = skipcolumnsmax;
  1080.  
  1081.     logerror("gfx_width = %d gfx_height = %d\n"
  1082.                 "gfx_xoffset = %d gfx_yoffset = %d\n"
  1083.                 "xmin %d ymin %d xmax %d ymax %d\n"
  1084.                 "skiplines %d skipcolumns %d\n"
  1085.                 "gfx_display_lines %d gfx_display_columns %d\n"
  1086.                 "xmultiply %d ymultiply %d\n",
  1087.                 gfx_width,gfx_height,
  1088.                 gfx_xoffset,gfx_yoffset,
  1089.                 xmin, ymin, xmax, ymax, skiplines, skipcolumns,gfx_display_lines,gfx_display_columns,xmultiply,ymultiply);
  1090.  
  1091.     set_ui_visarea (skipcolumns, skiplines, skipcolumns+gfx_display_columns-1, skiplines+gfx_display_lines-1);
  1092.  
  1093.     /* round to a multiple of 4 to avoid missing pixels on the right side */
  1094.     gfx_display_columns  = (gfx_display_columns + 3) & ~3;
  1095. }
  1096.  
  1097.  
  1098.  
  1099. int game_width;
  1100. int game_height;
  1101. int game_attributes;
  1102.  
  1103. /* Create a display screen, or window, large enough to accomodate a bitmap */
  1104. /* of the given dimensions. Attributes are the ones defined in driver.h. */
  1105. /* Return a osd_bitmap pointer or 0 in case of error. */
  1106. struct osd_bitmap *osd_create_display(int width,int height,int depth,int attributes)
  1107. {
  1108.     logerror("width %d, height %d\n", width,height);
  1109.  
  1110.     brightness = 100;
  1111.     brightness_paused_adjust = 1.0;
  1112.     dirty_bright = 1;
  1113.  
  1114.     if (frameskip < 0) frameskip = 0;
  1115.     if (frameskip >= FRAMESKIP_LEVELS) frameskip = FRAMESKIP_LEVELS-1;
  1116.  
  1117.  
  1118.  
  1119.     gone_to_gfx_mode = 0;
  1120.  
  1121.     /* Look if this is a vector game */
  1122.     if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
  1123.         vector_game = 1;
  1124.     else
  1125.         vector_game = 0;
  1126.  
  1127.  
  1128.     if (use_dirty == -1)    /* dirty=auto in mame.cfg? */
  1129.     {
  1130.         /* Is the game using a dirty system? */
  1131.         if ((Machine->drv->video_attributes & VIDEO_SUPPORTS_DIRTY) || vector_game)
  1132.             use_dirty = 1;
  1133.         else
  1134.             use_dirty = 0;
  1135.     }
  1136.  
  1137.     select_display_mode(depth);
  1138.  
  1139.     if (vector_game)
  1140.     {
  1141.         scale_vectorgames(gfx_width,gfx_height,&width, &height);
  1142.     }
  1143.  
  1144.     game_width = width;
  1145.     game_height = height;
  1146.     game_attributes = attributes;
  1147.  
  1148.     if (depth == 16)
  1149.         scrbitmap = osd_new_bitmap(width,height,16);
  1150.     else
  1151.         scrbitmap = osd_new_bitmap(width,height,8);
  1152.  
  1153.     if (!scrbitmap) return 0;
  1154.  
  1155. /* find a VESA driver for 15KHz modes just in case we need it later on */
  1156.     if (scanrate15KHz)
  1157.         getSVGA15KHzdriver (&SVGA15KHzdriver);
  1158.     else
  1159.         SVGA15KHzdriver = 0;
  1160.  
  1161.  
  1162.     if (!osd_set_display(width, height, attributes))
  1163.         return 0;
  1164.  
  1165.     /* center display based on visible area */
  1166.     if (vector_game)
  1167.         adjust_display(0, 0, width-1, height-1, depth);
  1168.     else
  1169.     {
  1170.         struct rectangle vis = Machine->drv->visible_area;
  1171.         adjust_display(vis.min_x, vis.min_y, vis.max_x, vis.max_y, depth);
  1172.     }
  1173.  
  1174.    /*Check for SVGA 15.75KHz mode (req. for 15.75KHz Arcade Monitor Modes)
  1175.      need to do this here, as the double params will be set up correctly */
  1176.     if (use_vesa == 1 && scanrate15KHz)
  1177.     {
  1178.         int dbl;
  1179.         dbl = (ymultiply >= 2);
  1180.         /* check that we found a driver */
  1181.         if (!SVGA15KHzdriver)
  1182.         {
  1183.             printf ("\nUnable to find 15.75KHz SVGA driver for %dx%d\n", gfx_width, gfx_height);
  1184.             return 0;
  1185.         }
  1186.         logerror("Using %s 15.75KHz SVGA driver\n", SVGA15KHzdriver->name);
  1187.         /*and try to set the mode */
  1188.         if (!SVGA15KHzdriver->setSVGA15KHzmode (dbl, gfx_width, gfx_height))
  1189.         {
  1190.             printf ("\nUnable to set SVGA 15.75KHz mode %dx%d (driver: %s)\n", gfx_width, gfx_height, SVGA15KHzdriver->name);
  1191.             return 0;
  1192.         }
  1193.         /* if we're doubling, we might as well have scanlines */
  1194.         /* the 15.75KHz driver is going to drop every other line anyway -
  1195.             so we can avoid drawing them and save some time */
  1196.         if(dbl)
  1197.             scanlines=1;
  1198.     }
  1199.  
  1200.     return scrbitmap;
  1201. }
  1202.  
  1203. /* set the actual display screen but don't allocate the screen bitmap */
  1204. int osd_set_display(int width,int height, int attributes)
  1205. {
  1206.     struct mode_adjust *adjust_array;
  1207.  
  1208.     int     i;
  1209.     /* moved 'found' to here (req. for 15.75KHz Arcade Monitor Modes) */
  1210.     int     found;
  1211.  
  1212.     if (!gfx_height || !gfx_width)
  1213.     {
  1214.         printf("Please specify height AND width (e.g. -640x480)\n");
  1215.         return 0;
  1216.     }
  1217.  
  1218.  
  1219.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  1220.     {
  1221.         int temp;
  1222.  
  1223.         temp = width;
  1224.         width = height;
  1225.         height = temp;
  1226.     }
  1227.     /* Mark the dirty buffers as dirty */
  1228.  
  1229.     if (use_dirty)
  1230.     {
  1231.         if (vector_game)
  1232.             /* vector games only use one dirty buffer */
  1233.             init_dirty (0);
  1234.         else
  1235.             init_dirty(1);
  1236.         swap_dirty();
  1237.         init_dirty(1);
  1238.     }
  1239.     if (dirtycolor)
  1240.     {
  1241.         for (i = 0;i < screen_colors;i++)
  1242.             dirtycolor[i] = 1;
  1243.         dirtypalette = 1;
  1244.     }
  1245.     /* handle special 15.75KHz modes, these now include SVGA modes */
  1246.     found = 0;
  1247.     /*move video freq set to here, as we need to set it explicitly for the 15.75KHz modes */
  1248.     videofreq = vgafreq;
  1249.  
  1250.     if (scanrate15KHz == 1)
  1251.     {
  1252.         /* pick the mode from our 15.75KHz tweaked modes */
  1253.         for (i=0; ((arcade_tweaked[i].x != 0) && !found); i++)
  1254.         {
  1255.             if (gfx_width  == arcade_tweaked[i].x &&
  1256.                 gfx_height == arcade_tweaked[i].y)
  1257.             {
  1258.                 /* check for SVGA mode with no vesa flag */
  1259.                 if (arcade_tweaked[i].vesa&& use_vesa == 0)
  1260.                 {
  1261.                     printf ("\n %dx%d SVGA 15.75KHz mode only available if tweaked flag is set to 0\n", gfx_width, gfx_height);
  1262.                     return 0;
  1263.                 }
  1264.                 /* check for a NTSC or PAL mode with no arcade flag */
  1265.                 if (monitor_type != MONITOR_TYPE_ARCADE)
  1266.                 {
  1267.                     if (arcade_tweaked[i].ntsc && monitor_type != MONITOR_TYPE_NTSC)
  1268.                     {
  1269.                         printf("\n %dx%d 15.75KHz mode only available if -monitor set to 'arcade' or 'ntsc' \n", gfx_width, gfx_height);
  1270.                         return 0;
  1271.                     }
  1272.                     if (!arcade_tweaked[i].ntsc && monitor_type != MONITOR_TYPE_PAL)
  1273.                     {
  1274.                         printf("\n %dx%d 15.75KHz mode only available if -monitor set to 'arcade' or 'pal' \n", gfx_width, gfx_height);
  1275.                         return 0;
  1276.                     }
  1277.  
  1278.                 }
  1279.  
  1280.                 reg = arcade_tweaked[i].reg;
  1281.                 reglen = arcade_tweaked[i].reglen;
  1282.                 use_vesa = arcade_tweaked[i].vesa;
  1283.                 half_yres = arcade_tweaked[i].half_yres;
  1284.                 /* all 15.75KHz VGA modes are unchained */
  1285.                 unchained = !use_vesa;
  1286.  
  1287.                 logerror("15.75KHz mode (%dx%d) vesa:%d half:%d unchained:%d\n",
  1288.                                         gfx_width, gfx_height, use_vesa, half_yres, unchained);
  1289.                 /* always use the freq from the structure */
  1290.                 videofreq = arcade_tweaked[i].syncvgafreq;
  1291.                 found = 1;
  1292.             }
  1293.         }
  1294.         /* explicitly asked for an 15.75KHz mode which doesn't exist , so inform and exit */
  1295.         if (!found)
  1296.         {
  1297.             printf ("\nNo %dx%d 15.75KHz mode available.\n", gfx_width, gfx_height);
  1298.             return 0;
  1299.         }
  1300.     }
  1301.  
  1302.     if (use_vesa != 1 && use_tweaked == 1)
  1303.     {
  1304.  
  1305.         /* setup tweaked modes */
  1306.         /* handle 57Hz games which fit into 60Hz mode */
  1307.         if (!found && gfx_width <= 256 && gfx_height <= 256 &&
  1308.                 video_sync && Machine->drv->frames_per_second == 57)
  1309.         {
  1310.             found = 1;
  1311.             if (!(Machine->orientation & ORIENTATION_SWAP_XY))
  1312.             {
  1313.                 reg = scr256x256hor;
  1314.                 reglen = sizeof(scr256x256hor)/sizeof(Register);
  1315.                 videofreq = 0;
  1316.             }
  1317.             else
  1318.             {
  1319.                 reg = scr256x256;
  1320.                 reglen = sizeof(scr256x256)/sizeof(Register);
  1321.                 videofreq = 1;
  1322.             }
  1323.         }
  1324.  
  1325.         /* find the matching tweaked mode */
  1326.         for (i=0; ((vga_tweaked[i].x != 0) && !found); i++)
  1327.         {
  1328.             if (gfx_width  == vga_tweaked[i].x &&
  1329.                 gfx_height == vga_tweaked[i].y)
  1330.             {
  1331.                 /* check for correct horizontal/vertical modes */
  1332.  
  1333.                 if((!vga_tweaked[i].vertical_mode && !(Machine->orientation & ORIENTATION_SWAP_XY)) ||
  1334.                     (vga_tweaked[i].vertical_mode && (Machine->orientation & ORIENTATION_SWAP_XY)))
  1335.                 {
  1336.                     reg = vga_tweaked[i].reg;
  1337.                     reglen = vga_tweaked[i].reglen;
  1338.                     if (videofreq == -1)
  1339.                         videofreq = vga_tweaked[i].syncvgafreq;
  1340.                     found = 1;
  1341.                     unchained = vga_tweaked[i].unchained;
  1342.                     if(unchained)
  1343.                     {
  1344.                         /* for unchained modes, turn off dirty updates */
  1345.                         /* as any speed gain is lost in the complex multi-page update needed */
  1346.                         /* plus - non-dirty updates remove unchained 'shearing' */
  1347.                         use_dirty = 0;
  1348.                     }
  1349.                 }
  1350.             }
  1351.         }
  1352.  
  1353.  
  1354.         /* can't find a VGA mode, use VESA */
  1355.         if (found == 0)
  1356.         {
  1357.             use_vesa = 1;
  1358.         }
  1359.         else
  1360.         {
  1361.             use_vesa = 0;
  1362.             if (videofreq < 0) videofreq = 0;
  1363.             else if (videofreq > 3) videofreq = 3;
  1364.         }
  1365.     }
  1366.  
  1367.     if (use_vesa != 0)
  1368.     {
  1369.         /*removed local 'found' */
  1370.         int mode, bits, err;
  1371.  
  1372.         mode = gfx_mode;
  1373.         found = 0;
  1374.         bits = scrbitmap->depth;
  1375.  
  1376.         /* Try the specified vesamode, 565 and 555 for 16 bit color modes, */
  1377.         /* doubled resolution in case of noscanlines and if not succesful  */
  1378.         /* repeat for all "lower" VESA modes. NS/BW 19980102 */
  1379.  
  1380.         while (!found)
  1381.         {
  1382.             set_color_depth(bits);
  1383.  
  1384.             /* allocate a wide enough virtual screen if possible */
  1385.             /* we round the width (in dwords) to be an even multiple 256 - that */
  1386.             /* way, during page flipping only one byte of the video RAM */
  1387.             /* address changes, therefore preventing flickering. */
  1388.             if (bits == 8)
  1389.                 triplebuf_page_width = (gfx_width + 0x3ff) & ~0x3ff;
  1390.             else
  1391.                 triplebuf_page_width = (gfx_width + 0x1ff) & ~0x1ff;
  1392.  
  1393.             /* don't ask for a larger screen if triplebuffer not requested - could */
  1394.             /* cause problems in some cases. */
  1395.             err = 1;
  1396.             if (use_triplebuf)
  1397.                 err = set_gfx_mode(mode,gfx_width,gfx_height,3*triplebuf_page_width,0);
  1398.             if (err)
  1399.             {
  1400.                 /* if we're using a SVGA 15KHz driver - tell Allegro the virtual screen width */
  1401.                 if(SVGA15KHzdriver)
  1402.                     err = set_gfx_mode(mode,gfx_width,gfx_height,SVGA15KHzdriver->getlogicalwidth(gfx_width),0);
  1403.                 else
  1404.                     err = set_gfx_mode(mode,gfx_width,gfx_height,0,0);
  1405.             }
  1406.  
  1407.             logerror("Trying ");
  1408.             if      (mode == GFX_VESA1)
  1409.                 logerror("VESA1");
  1410.             else if (mode == GFX_VESA2B)
  1411.                 logerror("VESA2B");
  1412.             else if (mode == GFX_VESA2L)
  1413.                 logerror("VESA2L");
  1414.             else if (mode == GFX_VESA3)
  1415.                 logerror("VESA3");
  1416.             logerror("  %dx%d, %d bit\n",
  1417.                     gfx_width, gfx_height, bits);
  1418.  
  1419.             if (err == 0)
  1420.             {
  1421.                 found = 1;
  1422.                 /* replace gfx_mode with found mode */
  1423.                 gfx_mode = mode;
  1424.                 continue;
  1425.             }
  1426.             else logerror("%s\n",allegro_error);
  1427.  
  1428.             /* Now adjust parameters for the next loop */
  1429.  
  1430.             /* try 5-5-5 in case there is no 5-6-5 16 bit color mode */
  1431.             if (scrbitmap->depth == 16)
  1432.             {
  1433.                 if (bits == 16)
  1434.                 {
  1435.                     bits = 15;
  1436.                     continue;
  1437.                 }
  1438.                 else
  1439.                     bits = 16; /* reset to 5-6-5 */
  1440.             }
  1441.  
  1442.             /* try VESA modes in VESA3-VESA2L-VESA2B-VESA1 order */
  1443.  
  1444.             if (mode == GFX_VESA3)
  1445.             {
  1446.                 mode = GFX_VESA2L;
  1447.                 continue;
  1448.             }
  1449.             else if (mode == GFX_VESA2L)
  1450.             {
  1451.                 mode = GFX_VESA2B;
  1452.                 continue;
  1453.             }
  1454.             else if (mode == GFX_VESA2B)
  1455.             {
  1456.                 mode = GFX_VESA1;
  1457.                 continue;
  1458.             }
  1459.             else if (mode == GFX_VESA1)
  1460.                 mode = gfx_mode; /* restart with the mode given in mame.cfg */
  1461.  
  1462.             /* try higher resolutions */
  1463.             if (auto_resolution)
  1464.             {
  1465.                 if (stretch && gfx_width <= 512)
  1466.                 {
  1467.                     /* low res VESA mode not available, try an high res one */
  1468.                     gfx_width *= 2;
  1469.                     gfx_height *= 2;
  1470.                     continue;
  1471.                 }
  1472.  
  1473.                 /* try next higher resolution */
  1474.                 if (gfx_height < 300 && gfx_width < 400)
  1475.                 {
  1476.                     gfx_width = 400;
  1477.                     gfx_height = 300;
  1478.                     continue;
  1479.                 }
  1480.                 else if (gfx_height < 384 && gfx_width < 512)
  1481.                 {
  1482.                     gfx_width = 512;
  1483.                     gfx_height = 384;
  1484.                     continue;
  1485.                 }
  1486.                 else if (gfx_height < 480 && gfx_width < 640)
  1487.                 {
  1488.                     gfx_width = 640;
  1489.                     gfx_height = 480;
  1490.                     continue;
  1491.                 }
  1492.                 else if (gfx_height < 600 && gfx_width < 800)
  1493.                 {
  1494.                     gfx_width = 800;
  1495.                     gfx_height = 600;
  1496.                     continue;
  1497.                 }
  1498.                 else if (gfx_height < 768 && gfx_width < 1024)
  1499.                 {
  1500.                     gfx_width = 1024;
  1501.                     gfx_height = 768;
  1502.                     continue;
  1503.                 }
  1504.             }
  1505.  
  1506.             /* If there was no continue up to this point, we give up */
  1507.             break;
  1508.         }
  1509.  
  1510.         if (found == 0)
  1511.         {
  1512.             printf ("\nNo %d-bit %dx%d VESA mode available.\n",
  1513.                     scrbitmap->depth,gfx_width,gfx_height);
  1514.             printf ("\nPossible causes:\n"
  1515. "1) Your video card does not support VESA modes at all. Almost all\n"
  1516. "   video cards support VESA modes natively these days, so you probably\n"
  1517. "   have an older card which needs some driver loaded first.\n"
  1518. "   In case you can't find such a driver in the software that came with\n"
  1519. "   your video card, Scitech Display Doctor or (for S3 cards) S3VBE\n"
  1520. "   are good alternatives.\n"
  1521. "2) Your VESA implementation does not support this resolution. For example,\n"
  1522. "   '-320x240', '-400x300' and '-512x384' are only supported by a few\n"
  1523. "   implementations.\n"
  1524. "3) Your video card doesn't support this resolution at this color depth.\n"
  1525. "   For example, 1024x768 in 16 bit colors requires 2MB video memory.\n"
  1526. "   You can either force an 8 bit video mode ('-depth 8') or use a lower\n"
  1527. "   resolution ('-640x480', '-800x600').\n");
  1528.             return 0;
  1529.         }
  1530.         else
  1531.         {
  1532.             logerror("Found matching %s mode\n", gfx_driver->desc);
  1533.             gfx_mode = mode;
  1534.             /* disable triple buffering if the screen is not large enough */
  1535.             logerror("Virtual screen size %dx%d\n",VIRTUAL_W,VIRTUAL_H);
  1536.             if (VIRTUAL_W < 3*triplebuf_page_width)
  1537.             {
  1538.                 use_triplebuf = 0;
  1539.                 logerror("Triple buffer disabled\n");
  1540.             }
  1541.  
  1542.             /* if triple buffering is enabled, turn off vsync */
  1543.             if (use_triplebuf)
  1544.             {
  1545.                 wait_vsync = 0;
  1546.                 video_sync = 0;
  1547.             }
  1548.         }
  1549.     }
  1550.     else
  1551.     {
  1552.  
  1553.  
  1554.         /* set the VGA clock */
  1555.         if (video_sync || always_synced || wait_vsync)
  1556.             reg[0].value = (reg[0].value & 0xf3) | (videofreq << 2);
  1557.  
  1558.         /* VGA triple buffering */
  1559.         if(use_triplebuf)
  1560.         {
  1561.  
  1562.             int vga_page_size = (gfx_width * gfx_height);
  1563.             /* see if it'll fit */
  1564.             if ((vga_page_size * 3) > 0x40000)
  1565.             {
  1566.                 /* too big */
  1567.                 logerror("tweaked mode %dx%d is too large to triple buffer\ntriple buffering disabled\n",gfx_width,gfx_height);
  1568.                 use_triplebuf = 0;
  1569.             }
  1570.             else
  1571.             {
  1572.                 /* it fits, so set up the 3 pages */
  1573.                 no_xpages = 3;
  1574.                 xpage_size = vga_page_size / 4;
  1575.                 logerror("unchained VGA triple buffering page size :%d\n",xpage_size);
  1576.                 /* and make sure the mode's unchained */
  1577.                 unchain_vga (reg);
  1578.                 /* triple buffering is enabled, turn off vsync */
  1579.                 wait_vsync = 0;
  1580.                 video_sync = 0;
  1581.             }
  1582.         }
  1583.         /* center the mode */
  1584.         center_mode (reg);
  1585.  
  1586.         /* set the horizontal and vertical total */
  1587.         if (scanrate15KHz)
  1588.             /* 15.75KHz modes */
  1589.             adjust_array = arcade_adjust;
  1590.         else
  1591.             /* PC monitor modes */
  1592.             adjust_array = pc_adjust;
  1593.  
  1594.         for (i=0; adjust_array[i].x != 0; i++)
  1595.         {
  1596.             if ((gfx_width == adjust_array[i].x) && (gfx_height == adjust_array[i].y))
  1597.             {
  1598.                 /* check for 'special vertical' modes */
  1599.                 if((!adjust_array[i].vertical_mode && !(Machine->orientation & ORIENTATION_SWAP_XY)) ||
  1600.                     (adjust_array[i].vertical_mode && (Machine->orientation & ORIENTATION_SWAP_XY)))
  1601.                 {
  1602.                     reg[H_TOTAL_INDEX].value = *adjust_array[i].hadjust;
  1603.                     reg[V_TOTAL_INDEX].value = *adjust_array[i].vadjust;
  1604.                     break;
  1605.                 }
  1606.             }
  1607.         }
  1608.  
  1609.         /*if scanlines were requested - change the array values to get a scanline mode */
  1610.         if (scanlines && !scanrate15KHz)
  1611.             reg = make_scanline_mode(reg,reglen);
  1612.  
  1613.         /* big hack: open a mode 13h screen using Allegro, then load the custom screen */
  1614.         /* definition over it. */
  1615.         if (set_gfx_mode(GFX_VGA,320,200,0,0) != 0)
  1616.             return 0;
  1617.  
  1618.         logerror("Generated Tweak Values :-\n");
  1619.         for (i=0; i<reglen; i++)
  1620.         {
  1621.             logerror("{ 0x%02x, 0x%02x, 0x%02x},",reg[i].port,reg[i].index,reg[i].value);
  1622.             if (!((i+1)%3))
  1623.                 logerror("\n");
  1624.         }
  1625.  
  1626.         /* tweak the mode */
  1627.         outRegArray(reg,reglen);
  1628.  
  1629.         /* check for unchained mode,  if unchained clear all pages */
  1630.         if (unchained)
  1631.         {
  1632.             unsigned long address;
  1633.             /* clear all 4 bit planes */
  1634.             outportw (0x3c4, (0x02 | (0x0f << 0x08)));
  1635.             for (address = 0xa0000; address < 0xb0000; address += 4)
  1636.                 _farpokel(screen->seg, address, 0);
  1637.         }
  1638.     }
  1639.  
  1640.  
  1641.     gone_to_gfx_mode = 1;
  1642.  
  1643.  
  1644.     vsync_frame_rate = Machine->drv->frames_per_second;
  1645.  
  1646.     if (video_sync)
  1647.     {
  1648.         TICKER a,b;
  1649.         float rate;
  1650.  
  1651.  
  1652.         /* wait some time to let everything stabilize */
  1653.         for (i = 0;i < 60;i++)
  1654.         {
  1655.             vsync();
  1656.             a = ticker();
  1657.         }
  1658.  
  1659.         /* small delay for really really fast machines */
  1660.         for (i = 0;i < 100000;i++) ;
  1661.  
  1662.         vsync();
  1663.         b = ticker();
  1664.  
  1665.         rate = ((float)TICKS_PER_SEC)/(b-a);
  1666.  
  1667.         logerror("target frame rate = %ffps, video frame rate = %3.2fHz\n",Machine->drv->frames_per_second,rate);
  1668.  
  1669.         /* don't allow more than 8% difference between target and actual frame rate */
  1670.         while (rate > Machine->drv->frames_per_second * 108 / 100)
  1671.             rate /= 2;
  1672.  
  1673.         if (rate < Machine->drv->frames_per_second * 92 / 100)
  1674.         {
  1675.             osd_close_display();
  1676.             logerror("-vsync option cannot be used with this display mode:\n"
  1677.                         "video refresh frequency = %dHz, target frame rate = %ffps\n",
  1678.                         (int)(TICKS_PER_SEC/(b-a)),Machine->drv->frames_per_second);
  1679.             return 0;
  1680.         }
  1681.  
  1682.         logerror("adjusted video frame rate = %3.2fHz\n",rate);
  1683.             vsync_frame_rate = rate;
  1684.  
  1685.         if (Machine->sample_rate)
  1686.         {
  1687.             Machine->sample_rate = Machine->sample_rate * Machine->drv->frames_per_second / rate;
  1688.             logerror("sample rate adjusted to match video freq: %d\n",Machine->sample_rate);
  1689.         }
  1690.     }
  1691.  
  1692.     warming_up = 1;
  1693.  
  1694.     return 1;
  1695. }
  1696.  
  1697.  
  1698.  
  1699. /* shut up the display */
  1700. void osd_close_display(void)
  1701. {
  1702.     if (gone_to_gfx_mode != 0)
  1703.     {
  1704.         /* tidy up if 15.75KHz SVGA mode used */
  1705.         if (scanrate15KHz && use_vesa == 1)
  1706.         {
  1707.             /* check we've got a valid driver before calling it */
  1708.             if (SVGA15KHzdriver != NULL)
  1709.                 SVGA15KHzdriver->resetSVGA15KHzmode();
  1710.         }
  1711.  
  1712.         set_gfx_mode (GFX_TEXT,0,0,0,0);
  1713.  
  1714.         if (frames_displayed > FRAMES_TO_SKIP)
  1715.             printf("Average FPS: %f\n",(double)TICKS_PER_SEC/(end_time-start_time)*(frames_displayed-FRAMES_TO_SKIP));
  1716.     }
  1717.  
  1718.     free(dirtycolor);
  1719.     dirtycolor = 0;
  1720.     free(current_palette);
  1721.     current_palette = 0;
  1722.     free(palette_16bit_lookup);
  1723.     palette_16bit_lookup = 0;
  1724.     if (scrbitmap)
  1725.     {
  1726.         osd_free_bitmap(scrbitmap);
  1727.         scrbitmap = NULL;
  1728.     }
  1729. }
  1730.  
  1731.  
  1732.  
  1733. int osd_allocate_colors(unsigned int totalcolors,const unsigned char *palette,unsigned short *pens,int modifiable)
  1734. {
  1735.     int i;
  1736.  
  1737.     modifiable_palette = modifiable;
  1738.     screen_colors = totalcolors;
  1739.     if (scrbitmap->depth != 8)
  1740.         screen_colors += 2;
  1741.     else screen_colors = 256;
  1742.  
  1743.     dirtycolor = malloc(screen_colors * sizeof(int));
  1744.     current_palette = malloc(3 * screen_colors * sizeof(unsigned char));
  1745.     palette_16bit_lookup = malloc(screen_colors * sizeof(palette_16bit_lookup[0]));
  1746.     if (dirtycolor == 0 || current_palette == 0 || palette_16bit_lookup == 0)
  1747.         return 1;
  1748.  
  1749.     for (i = 0;i < screen_colors;i++)
  1750.         dirtycolor[i] = 1;
  1751.     dirtypalette = 1;
  1752.     for (i = 0;i < screen_colors;i++)
  1753.         current_palette[3*i+0] = current_palette[3*i+1] = current_palette[3*i+2] = 0;
  1754.  
  1755.     if (scrbitmap->depth != 8 && modifiable == 0)
  1756.     {
  1757.         int r,g,b;
  1758.  
  1759.  
  1760.         for (i = 0;i < totalcolors;i++)
  1761.         {
  1762.             r = 255 * brightness * pow(palette[3*i+0] / 255.0, 1 / osd_gamma_correction) / 100;
  1763.             g = 255 * brightness * pow(palette[3*i+1] / 255.0, 1 / osd_gamma_correction) / 100;
  1764.             b = 255 * brightness * pow(palette[3*i+2] / 255.0, 1 / osd_gamma_correction) / 100;
  1765.             *pens++ = makecol(r,g,b);
  1766.         }
  1767.  
  1768.         Machine->uifont->colortable[0] = makecol(0x00,0x00,0x00);
  1769.         Machine->uifont->colortable[1] = makecol(0xff,0xff,0xff);
  1770.         Machine->uifont->colortable[2] = makecol(0xff,0xff,0xff);
  1771.         Machine->uifont->colortable[3] = makecol(0x00,0x00,0x00);
  1772.     }
  1773.     else
  1774.     {
  1775.         if (scrbitmap->depth == 8 && totalcolors >= 255)
  1776.         {
  1777.             int bestblack,bestwhite;
  1778.             int bestblackscore,bestwhitescore;
  1779.  
  1780.  
  1781.             bestblack = bestwhite = 0;
  1782.             bestblackscore = 3*255*255;
  1783.             bestwhitescore = 0;
  1784.             for (i = 0;i < totalcolors;i++)
  1785.             {
  1786.                 int r,g,b,score;
  1787.  
  1788.                 r = palette[3*i+0];
  1789.                 g = palette[3*i+1];
  1790.                 b = palette[3*i+2];
  1791.                 score = r*r + g*g + b*b;
  1792.  
  1793.                 if (score < bestblackscore)
  1794.                 {
  1795.                     bestblack = i;
  1796.                     bestblackscore = score;
  1797.                 }
  1798.                 if (score > bestwhitescore)
  1799.                 {
  1800.                     bestwhite = i;
  1801.                     bestwhitescore = score;
  1802.                 }
  1803.             }
  1804.  
  1805.             for (i = 0;i < totalcolors;i++)
  1806.                 pens[i] = i;
  1807.  
  1808.             /* map black to pen 0, otherwise the screen border will not be black */
  1809.             pens[bestblack] = 0;
  1810.             pens[0] = bestblack;
  1811.  
  1812.             Machine->uifont->colortable[0] = pens[bestblack];
  1813.             Machine->uifont->colortable[1] = pens[bestwhite];
  1814.             Machine->uifont->colortable[2] = pens[bestwhite];
  1815.             Machine->uifont->colortable[3] = pens[bestblack];
  1816.         }
  1817.         else
  1818.         {
  1819.             /* reserve color 1 for the user interface text */
  1820.             current_palette[3*1+0] = current_palette[3*1+1] = current_palette[3*1+2] = 0xff;
  1821.             Machine->uifont->colortable[0] = 0;
  1822.             Machine->uifont->colortable[1] = 1;
  1823.             Machine->uifont->colortable[2] = 1;
  1824.             Machine->uifont->colortable[3] = 0;
  1825.  
  1826.             /* fill the palette starting from the end, so we mess up badly written */
  1827.             /* drivers which don't go through Machine->pens[] */
  1828.             for (i = 0;i < totalcolors;i++)
  1829.                 pens[i] = (screen_colors-1)-i;
  1830.         }
  1831.  
  1832.         for (i = 0;i < totalcolors;i++)
  1833.         {
  1834.             current_palette[3*pens[i]+0] = palette[3*i];
  1835.             current_palette[3*pens[i]+1] = palette[3*i+1];
  1836.             current_palette[3*pens[i]+2] = palette[3*i+2];
  1837.         }
  1838.     }
  1839.  
  1840.     if (use_vesa == 0)
  1841.     {
  1842.         if (use_dirty) /* supports dirty ? */
  1843.         {
  1844.             if (unchained)
  1845.             {
  1846.                 update_screen = blitscreen_dirty1_unchained_vga;
  1847.                 logerror("blitscreen_dirty1_unchained_vga\n");
  1848.             }
  1849.             else
  1850.             {
  1851.                 update_screen = blitscreen_dirty1_vga;
  1852.                 logerror("blitscreen_dirty1_vga\n");
  1853.             }
  1854.         }
  1855.         else
  1856.         {
  1857.             /* check for unchained modes */
  1858.             if (unchained)
  1859.             {
  1860.                 update_screen = blitscreen_dirty0_unchained_vga;
  1861.                 logerror("blitscreen_dirty0_unchained_vga\n");
  1862.             }
  1863.             else
  1864.             {
  1865.                 update_screen = blitscreen_dirty0_vga;
  1866.                 logerror("blitscreen_dirty0_vga\n");
  1867.             }
  1868.         }
  1869.     }
  1870.     else
  1871.     {
  1872.         if (use_mmx == -1) /* mmx=auto: can new mmx blitters be applied? */
  1873.         {
  1874.             /* impossible cases follow */
  1875.             if (!cpu_mmx)
  1876.                 mmxlfb = 0;
  1877.             else if ((gfx_mode != GFX_VESA2L) && (gfx_mode != GFX_VESA3))
  1878.                 mmxlfb = 0;
  1879.             /* not yet implemented cases follow */
  1880.             else if ((xmultiply > 2) || (ymultiply > 2))
  1881.                 mmxlfb = 0;
  1882.             else
  1883.                 mmxlfb = 1;
  1884.         }
  1885.         else /* use forced mmx= setting from mame.cfg at own risk!!! */
  1886.             mmxlfb = use_mmx;
  1887.  
  1888.         if (scrbitmap->depth == 16)
  1889.         {
  1890.             if (modifiable_palette)
  1891.                 update_screen = updaters16_palettized[xmultiply-1][ymultiply-1][scanlines?1:0][use_dirty?1:0];
  1892.             else
  1893.                 update_screen = updaters16[xmultiply-1][ymultiply-1][scanlines?1:0][use_dirty?1:0];
  1894.         }
  1895.         else
  1896.         {
  1897.             update_screen = updaters8[xmultiply-1][ymultiply-1][scanlines?1:0][use_dirty?1:0];
  1898.         }
  1899.     }
  1900.  
  1901.     return 0;
  1902. }
  1903.  
  1904.  
  1905. void osd_modify_pen(int pen,unsigned char red, unsigned char green, unsigned char blue)
  1906. {
  1907.     if (modifiable_palette == 0)
  1908.     {
  1909.         logerror("error: osd_modify_pen() called with modifiable_palette == 0\n");
  1910.         return;
  1911.     }
  1912.  
  1913.  
  1914.     if (    current_palette[3*pen+0] != red ||
  1915.             current_palette[3*pen+1] != green ||
  1916.             current_palette[3*pen+2] != blue)
  1917.     {
  1918.         current_palette[3*pen+0] = red;
  1919.         current_palette[3*pen+1] = green;
  1920.         current_palette[3*pen+2] = blue;
  1921.  
  1922.         dirtycolor[pen] = 1;
  1923.         dirtypalette = 1;
  1924.     }
  1925. }
  1926.  
  1927.  
  1928.  
  1929. void osd_get_pen(int pen,unsigned char *red, unsigned char *green, unsigned char *blue)
  1930. {
  1931.     if (scrbitmap->depth != 8 && modifiable_palette == 0)
  1932.     {
  1933.         *red =   getr(pen);
  1934.         *green = getg(pen);
  1935.         *blue =  getb(pen);
  1936.     }
  1937.     else
  1938.     {
  1939.         *red =   current_palette[3*pen+0];
  1940.         *green = current_palette[3*pen+1];
  1941.         *blue =  current_palette[3*pen+2];
  1942.     }
  1943. }
  1944.  
  1945.  
  1946.  
  1947. void update_screen_dummy(void)
  1948. {
  1949.     logerror("msdos/video.c: undefined update_screen() function for %d x %d!\n",xmultiply,ymultiply);
  1950. }
  1951.  
  1952. INLINE void pan_display(void)
  1953. {
  1954.     int pan_changed = 0;
  1955.  
  1956.     /* horizontal panning */
  1957.     if (input_ui_pressed_repeat(IPT_UI_PAN_LEFT,1))
  1958.         if (skipcolumns < skipcolumnsmax)
  1959.         {
  1960.             skipcolumns++;
  1961.             osd_mark_dirty (0,0,scrbitmap->width-1,scrbitmap->height-1,1);
  1962.             pan_changed = 1;
  1963.         }
  1964.     if (input_ui_pressed_repeat(IPT_UI_PAN_RIGHT,1))
  1965.         if (skipcolumns > skipcolumnsmin)
  1966.         {
  1967.             skipcolumns--;
  1968.             osd_mark_dirty (0,0,scrbitmap->width-1,scrbitmap->height-1,1);
  1969.             pan_changed = 1;
  1970.         }
  1971.     if (input_ui_pressed_repeat(IPT_UI_PAN_DOWN,1))
  1972.         if (skiplines < skiplinesmax)
  1973.         {
  1974.             skiplines++;
  1975.             osd_mark_dirty (0,0,scrbitmap->width-1,scrbitmap->height-1,1);
  1976.             pan_changed = 1;
  1977.         }
  1978.     if (input_ui_pressed_repeat(IPT_UI_PAN_UP,1))
  1979.         if (skiplines > skiplinesmin)
  1980.         {
  1981.             skiplines--;
  1982.             osd_mark_dirty (0,0,scrbitmap->width-1,scrbitmap->height-1,1);
  1983.             pan_changed = 1;
  1984.         }
  1985.  
  1986.     if (pan_changed)
  1987.     {
  1988.         if (use_dirty) init_dirty(1);
  1989.  
  1990.         set_ui_visarea (skipcolumns, skiplines, skipcolumns+gfx_display_columns-1, skiplines+gfx_display_lines-1);
  1991.     }
  1992. }
  1993.  
  1994.  
  1995.  
  1996. int osd_skip_this_frame(void)
  1997. {
  1998.     static const int skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
  1999.     {
  2000.         { 0,0,0,0,0,0,0,0,0,0,0,0 },
  2001.         { 0,0,0,0,0,0,0,0,0,0,0,1 },
  2002.         { 0,0,0,0,0,1,0,0,0,0,0,1 },
  2003.         { 0,0,0,1,0,0,0,1,0,0,0,1 },
  2004.         { 0,0,1,0,0,1,0,0,1,0,0,1 },
  2005.         { 0,1,0,0,1,0,1,0,0,1,0,1 },
  2006.         { 0,1,0,1,0,1,0,1,0,1,0,1 },
  2007.         { 0,1,0,1,1,0,1,0,1,1,0,1 },
  2008.         { 0,1,1,0,1,1,0,1,1,0,1,1 },
  2009.         { 0,1,1,1,0,1,1,1,0,1,1,1 },
  2010.         { 0,1,1,1,1,1,0,1,1,1,1,1 },
  2011.         { 0,1,1,1,1,1,1,1,1,1,1,1 }
  2012.     };
  2013.  
  2014.     return skiptable[frameskip][frameskip_counter];
  2015. }
  2016.  
  2017. /* Update the display. */
  2018. void osd_update_video_and_audio(void)
  2019. {
  2020.     static const int waittable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS] =
  2021.     {
  2022.         { 1,1,1,1,1,1,1,1,1,1,1,1 },
  2023.         { 2,1,1,1,1,1,1,1,1,1,1,0 },
  2024.         { 2,1,1,1,1,0,2,1,1,1,1,0 },
  2025.         { 2,1,1,0,2,1,1,0,2,1,1,0 },
  2026.         { 2,1,0,2,1,0,2,1,0,2,1,0 },
  2027.         { 2,0,2,1,0,2,0,2,1,0,2,0 },
  2028.         { 2,0,2,0,2,0,2,0,2,0,2,0 },
  2029.         { 2,0,2,0,0,3,0,2,0,0,3,0 },
  2030.         { 3,0,0,3,0,0,3,0,0,3,0,0 },
  2031.         { 4,0,0,0,4,0,0,0,4,0,0,0 },
  2032.         { 6,0,0,0,0,0,6,0,0,0,0,0 },
  2033.         {12,0,0,0,0,0,0,0,0,0,0,0 }
  2034.     };
  2035.     int i;
  2036.     static int showfps,showfpstemp;
  2037.     TICKER curr;
  2038.     static TICKER prev_measure,this_frame_base,prev;
  2039.     static int speed = 100;
  2040.     static int vups,vfcount;
  2041.     int have_to_clear_bitmap = 0;
  2042.     int already_synced;
  2043.  
  2044.  
  2045.     if (warming_up)
  2046.     {
  2047.         /* first time through, initialize timer */
  2048.         prev_measure = ticker() - FRAMESKIP_LEVELS * TICKS_PER_SEC/Machine->drv->frames_per_second;
  2049.         warming_up = 0;
  2050.     }
  2051.  
  2052.     if (frameskip_counter == 0)
  2053.         this_frame_base = prev_measure + FRAMESKIP_LEVELS * TICKS_PER_SEC/Machine->drv->frames_per_second;
  2054.  
  2055.     if (throttle)
  2056.     {
  2057.         static TICKER last;
  2058.  
  2059.         /* if too much time has passed since last sound update, disable throttling */
  2060.         /* temporarily - we wouldn't be able to keep synch anyway. */
  2061.         curr = ticker();
  2062.         if ((curr - last) > 2*TICKS_PER_SEC / Machine->drv->frames_per_second)
  2063.             throttle = 0;
  2064.         last = curr;
  2065.  
  2066.         already_synced = msdos_update_audio();
  2067.  
  2068.         throttle = 1;
  2069.     }
  2070.     else
  2071.         already_synced = msdos_update_audio();
  2072.  
  2073.  
  2074.     if (osd_skip_this_frame() == 0)
  2075.     {
  2076.         if (showfpstemp)
  2077.         {
  2078.             showfpstemp--;
  2079.             if (showfps == 0 && showfpstemp == 0)
  2080.             {
  2081.                 have_to_clear_bitmap = 1;
  2082.             }
  2083.         }
  2084.  
  2085.  
  2086.         if (input_ui_pressed(IPT_UI_SHOW_FPS))
  2087.         {
  2088.             if (showfpstemp)
  2089.             {
  2090.                 showfpstemp = 0;
  2091.                 have_to_clear_bitmap = 1;
  2092.             }
  2093.             else
  2094.             {
  2095.                 showfps ^= 1;
  2096.                 if (showfps == 0)
  2097.                 {
  2098.                     have_to_clear_bitmap = 1;
  2099.                 }
  2100.             }
  2101.         }
  2102.  
  2103.  
  2104.         /* now wait until it's time to update the screen */
  2105.         if (throttle)
  2106.         {
  2107.             profiler_mark(PROFILER_IDLE);
  2108.             if (video_sync)
  2109.             {
  2110.                 static TICKER last;
  2111.  
  2112.  
  2113.                 do
  2114.                 {
  2115.                     vsync();
  2116.                     curr = ticker();
  2117.                 } while (TICKS_PER_SEC / (curr - last) > Machine->drv->frames_per_second * 11 /10);
  2118.  
  2119.                 last = curr;
  2120.             }
  2121.             else
  2122.             {
  2123.                 TICKER target;
  2124.  
  2125.  
  2126.                 /* wait for video sync but use normal throttling */
  2127.                 if (wait_vsync)
  2128.                     vsync();
  2129.  
  2130.                 curr = ticker();
  2131.  
  2132.                 if (already_synced == 0)
  2133.                 {
  2134.                 /* wait only if the audio update hasn't synced us already */
  2135.  
  2136.                     target = this_frame_base +
  2137.                             frameskip_counter * TICKS_PER_SEC/Machine->drv->frames_per_second;
  2138.  
  2139.                     if (curr - target < 0)
  2140.                     {
  2141.                         do
  2142.                         {
  2143.                             curr = ticker();
  2144.                         } while (curr - target < 0);
  2145.                     }
  2146.                 }
  2147.  
  2148.             }
  2149.             profiler_mark(PROFILER_END);
  2150.         }
  2151.         else curr = ticker();
  2152.  
  2153.  
  2154.         /* for the FPS average calculation */
  2155.         if (++frames_displayed == FRAMES_TO_SKIP)
  2156.             start_time = curr;
  2157.         else
  2158.             end_time = curr;
  2159.  
  2160.  
  2161.         if (frameskip_counter == 0)
  2162.         {
  2163.             int divdr;
  2164.  
  2165.  
  2166.             divdr = Machine->drv->frames_per_second * (curr - prev_measure) / (100 * FRAMESKIP_LEVELS);
  2167.             speed = (TICKS_PER_SEC + divdr/2) / divdr;
  2168.  
  2169.             prev_measure = curr;
  2170.         }
  2171.  
  2172.         prev = curr;
  2173.  
  2174.         vfcount += waittable[frameskip][frameskip_counter];
  2175.         if (vfcount >= Machine->drv->frames_per_second)
  2176.         {
  2177.             extern int vector_updates; /* avgdvg_go_w()'s per Mame frame, should be 1 */
  2178.  
  2179.  
  2180.             vfcount = 0;
  2181.             vups = vector_updates;
  2182.             vector_updates = 0;
  2183.         }
  2184.  
  2185.         if (showfps || showfpstemp)
  2186.         {
  2187.             int fps;
  2188.             char buf[30];
  2189.             int divdr;
  2190.  
  2191.  
  2192.             divdr = 100 * FRAMESKIP_LEVELS;
  2193.             fps = (Machine->drv->frames_per_second * (FRAMESKIP_LEVELS - frameskip) * speed + (divdr / 2)) / divdr;
  2194.             sprintf(buf,"%s%2d%4d%%%4d/%d fps",autoframeskip?"auto":"fskp",frameskip,speed,fps,(int)(Machine->drv->frames_per_second+0.5));
  2195.             ui_text(scrbitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,0);
  2196.             if (vector_game)
  2197.             {
  2198.                 sprintf(buf," %d vector updates",vups);
  2199.                 ui_text(scrbitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,Machine->uifontheight);
  2200.             }
  2201.         }
  2202.  
  2203.         if (scrbitmap->depth == 8)
  2204.         {
  2205.             if (dirty_bright)
  2206.             {
  2207.                 dirty_bright = 0;
  2208.                 for (i = 0;i < 256;i++)
  2209.                 {
  2210.                     float rate = brightness * brightness_paused_adjust * pow(i / 255.0, 1 / osd_gamma_correction) / 100;
  2211.                     bright_lookup[i] = 63 * rate + 0.5;
  2212.                 }
  2213.             }
  2214.             if (dirtypalette)
  2215.             {
  2216.                 dirtypalette = 0;
  2217.                 for (i = 0;i < screen_colors;i++)
  2218.                 {
  2219.                     if (dirtycolor[i])
  2220.                     {
  2221.                         RGB adjusted_palette;
  2222.  
  2223.                         dirtycolor[i] = 0;
  2224.  
  2225.                         adjusted_palette.r = current_palette[3*i+0];
  2226.                         adjusted_palette.g = current_palette[3*i+1];
  2227.                         adjusted_palette.b = current_palette[3*i+2];
  2228.                         if (i != Machine->uifont->colortable[1])    /* don't adjust the user interface text */
  2229.                         {
  2230.                             adjusted_palette.r = bright_lookup[adjusted_palette.r];
  2231.                             adjusted_palette.g = bright_lookup[adjusted_palette.g];
  2232.                             adjusted_palette.b = bright_lookup[adjusted_palette.b];
  2233.                         }
  2234.                         else
  2235.                         {
  2236.                             adjusted_palette.r >>= 2;
  2237.                             adjusted_palette.g >>= 2;
  2238.                             adjusted_palette.b >>= 2;
  2239.                         }
  2240.                         set_color(i,&adjusted_palette);
  2241.                     }
  2242.                 }
  2243.             }
  2244.         }
  2245.         else
  2246.         {
  2247.             if (dirty_bright)
  2248.             {
  2249.                 dirty_bright = 0;
  2250.                 for (i = 0;i < 256;i++)
  2251.                 {
  2252.                     float rate = brightness * brightness_paused_adjust * pow(i / 255.0, 1 / osd_gamma_correction) / 100;
  2253.                     bright_lookup[i] = 255 * rate + 0.5;
  2254.                 }
  2255.             }
  2256.             if (dirtypalette)
  2257.             {
  2258.                 if (use_dirty) init_dirty(1);    /* have to redraw the whole screen */
  2259.  
  2260.                 dirtypalette = 0;
  2261.                 for (i = 0;i < screen_colors;i++)
  2262.                 {
  2263.                     if (dirtycolor[i])
  2264.                     {
  2265.                         int r,g,b;
  2266.  
  2267.                         dirtycolor[i] = 0;
  2268.  
  2269.                         r = current_palette[3*i+0];
  2270.                         g = current_palette[3*i+1];
  2271.                         b = current_palette[3*i+2];
  2272.                         if (i != Machine->uifont->colortable[1])    /* don't adjust the user interface text */
  2273.                         {
  2274.                             r = bright_lookup[r];
  2275.                             g = bright_lookup[g];
  2276.                             b = bright_lookup[b];
  2277.                         }
  2278.                         palette_16bit_lookup[i] = makecol(r,g,b) * 0x10001;
  2279.                     }
  2280.                 }
  2281.             }
  2282.         }
  2283.  
  2284.         /* copy the bitmap to screen memory */
  2285.         profiler_mark(PROFILER_BLIT);
  2286.         update_screen();
  2287.         profiler_mark(PROFILER_END);
  2288.  
  2289.         /* see if we need to give the card enough time to draw both odd/even fields of the interlaced display
  2290.             (req. for 15.75KHz Arcade Monitor Modes */
  2291.         interlace_sync();
  2292.  
  2293.  
  2294.         if (have_to_clear_bitmap)
  2295.             osd_clearbitmap(scrbitmap);
  2296.  
  2297.         if (use_dirty)
  2298.         {
  2299.             if (!vector_game)
  2300.                 swap_dirty();
  2301.             init_dirty(0);
  2302.         }
  2303.  
  2304.         if (have_to_clear_bitmap)
  2305.             osd_clearbitmap(scrbitmap);
  2306.  
  2307.  
  2308.         if (throttle && autoframeskip && frameskip_counter == 0)
  2309.         {
  2310.             static int frameskipadjust;
  2311.             int adjspeed;
  2312.  
  2313.             /* adjust speed to video refresh rate if vsync is on */
  2314.             adjspeed = speed * Machine->drv->frames_per_second / vsync_frame_rate;
  2315.  
  2316.             if (adjspeed >= 100)
  2317.             {
  2318.                 frameskipadjust++;
  2319.                 if (frameskipadjust >= 3)
  2320.                 {
  2321.                     frameskipadjust = 0;
  2322.                     if (frameskip > 0) frameskip--;
  2323.                 }
  2324.             }
  2325.             else
  2326.             {
  2327.                 if (adjspeed < 80)
  2328.                     frameskipadjust -= (90 - adjspeed) / 5;
  2329.                 else
  2330.                 {
  2331.                     /* don't push frameskip too far if we are close to 100% speed */
  2332.                     if (frameskip < 8)
  2333.                         frameskipadjust--;
  2334.                 }
  2335.  
  2336.                 while (frameskipadjust <= -2)
  2337.                 {
  2338.                     frameskipadjust += 2;
  2339.                     if (frameskip < FRAMESKIP_LEVELS-1) frameskip++;
  2340.                 }
  2341.             }
  2342.         }
  2343.     }
  2344.  
  2345.     /* Check for PGUP, PGDN and pan screen */
  2346.     pan_display();
  2347.  
  2348.     if (input_ui_pressed(IPT_UI_FRAMESKIP_INC))
  2349.     {
  2350.         if (autoframeskip)
  2351.         {
  2352.             autoframeskip = 0;
  2353.             frameskip = 0;
  2354.         }
  2355.         else
  2356.         {
  2357.             if (frameskip == FRAMESKIP_LEVELS-1)
  2358.             {
  2359.                 frameskip = 0;
  2360.                 autoframeskip = 1;
  2361.             }
  2362.             else
  2363.                 frameskip++;
  2364.         }
  2365.  
  2366.         if (showfps == 0)
  2367.             showfpstemp = 2*Machine->drv->frames_per_second;
  2368.  
  2369.         /* reset the frame counter every time the frameskip key is pressed, so */
  2370.         /* we'll measure the average FPS on a consistent status. */
  2371.         frames_displayed = 0;
  2372.     }
  2373.  
  2374.     if (input_ui_pressed(IPT_UI_FRAMESKIP_DEC))
  2375.     {
  2376.         if (autoframeskip)
  2377.         {
  2378.             autoframeskip = 0;
  2379.             frameskip = FRAMESKIP_LEVELS-1;
  2380.         }
  2381.         else
  2382.         {
  2383.             if (frameskip == 0)
  2384.                 autoframeskip = 1;
  2385.             else
  2386.                 frameskip--;
  2387.         }
  2388.  
  2389.         if (showfps == 0)
  2390.             showfpstemp = 2*Machine->drv->frames_per_second;
  2391.  
  2392.         /* reset the frame counter every time the frameskip key is pressed, so */
  2393.         /* we'll measure the average FPS on a consistent status. */
  2394.         frames_displayed = 0;
  2395.     }
  2396.  
  2397.     if (input_ui_pressed(IPT_UI_THROTTLE))
  2398.     {
  2399.         throttle ^= 1;
  2400.  
  2401.         /* reset the frame counter every time the throttle key is pressed, so */
  2402.         /* we'll measure the average FPS on a consistent status. */
  2403.         frames_displayed = 0;
  2404.     }
  2405.  
  2406.  
  2407.     frameskip_counter = (frameskip_counter + 1) % FRAMESKIP_LEVELS;
  2408. }
  2409.  
  2410.  
  2411.  
  2412. void osd_set_gamma(float _gamma)
  2413. {
  2414.     int i;
  2415.  
  2416.     osd_gamma_correction = _gamma;
  2417.  
  2418.     for (i = 0;i < screen_colors;i++)
  2419.         dirtycolor[i] = 1;
  2420.     dirtypalette = 1;
  2421.     dirty_bright = 1;
  2422. }
  2423.  
  2424. float osd_get_gamma(void)
  2425. {
  2426.     return osd_gamma_correction;
  2427. }
  2428.  
  2429. /* brightess = percentage 0-100% */
  2430. void osd_set_brightness(int _brightness)
  2431. {
  2432.     int i;
  2433.  
  2434.     brightness = _brightness;
  2435.  
  2436.     for (i = 0;i < screen_colors;i++)
  2437.         dirtycolor[i] = 1;
  2438.     dirtypalette = 1;
  2439.     dirty_bright = 1;
  2440. }
  2441.  
  2442. int osd_get_brightness(void)
  2443. {
  2444.     return brightness;
  2445. }
  2446.  
  2447.  
  2448. void osd_save_snapshot(void)
  2449. {
  2450.     save_screen_snapshot();
  2451. }
  2452.  
  2453. void osd_pause(int paused)
  2454. {
  2455.     int i;
  2456.  
  2457.     if (paused) brightness_paused_adjust = 0.65;
  2458.     else brightness_paused_adjust = 1.0;
  2459.  
  2460.     for (i = 0;i < screen_colors;i++)
  2461.         dirtycolor[i] = 1;
  2462.     dirtypalette = 1;
  2463.     dirty_bright = 1;
  2464. }
  2465.  
  2466. Register *make_scanline_mode(Register *inreg,int entries)
  2467. {
  2468.     static Register outreg[32];
  2469.     int maxscan,maxscanout;
  2470.     int overflow,overflowout;
  2471.     int ytotalin,ytotalout;
  2472.     int ydispin,ydispout;
  2473.     int vrsin,vrsout,vreout,vblksout,vblkeout;
  2474. /* first - check's it not already a 'non doubled' line mode */
  2475.     maxscan = inreg[MAXIMUM_SCANLINE_INDEX].value;
  2476.     if ((maxscan & 1) == 0)
  2477.     /* it is, so just return the array as is */
  2478.           return inreg;
  2479. /* copy across our standard display array */
  2480.     memcpy (&outreg, inreg, entries * sizeof(Register));
  2481. /* keep hold of the overflow register - as we'll need to refer to it a lot */
  2482.     overflow = inreg[OVERFLOW_INDEX].value;
  2483. /* set a large line compare value  - as we won't be doing any split window scrolling etc.*/
  2484.     maxscanout = 0x40;
  2485. /* half all the y values */
  2486. /* total */
  2487.     ytotalin = inreg[V_TOTAL_INDEX].value;
  2488.     ytotalin |= ((overflow & 1)<<0x08) | ((overflow & 0x20)<<0x04);
  2489.     ytotalout = ytotalin >> 1;
  2490. /* display enable end */
  2491.     ydispin = inreg[13].value | ((overflow & 0x02)<< 0x07) | ((overflow & 0x040) << 0x03);
  2492.     ydispin ++;
  2493.     ydispout = ydispin >> 1;
  2494.     ydispout --;
  2495.     overflowout = ((ydispout & 0x100) >> 0x07) | ((ydispout && 0x200) >> 0x03);
  2496.     outreg[V_END_INDEX].value = (ydispout & 0xff);
  2497. /* avoid top over scan */
  2498.     if ((ytotalin - ydispin) < 40 && !center_y)
  2499.     {
  2500.           vrsout = ydispout;
  2501.         /* give ourselves a scanline cushion */
  2502.         ytotalout += 2;
  2503.     }
  2504.       else
  2505.     {
  2506. /* vertical retrace start */
  2507.         vrsin = inreg[V_RETRACE_START_INDEX].value | ((overflow & 0x04)<<0x06) | ((overflow & 0x80)<<0x02);
  2508.         vrsout = vrsin >> 1;
  2509.     }
  2510. /* check it's legal */
  2511.     if (vrsout < ydispout)
  2512.         vrsout = ydispout;
  2513. /*update our output overflow */
  2514.     overflowout |= (((vrsout & 0x100) >> 0x06) | ((vrsout & 0x200) >> 0x02));
  2515.     outreg[V_RETRACE_START_INDEX].value = (vrsout & 0xff);
  2516. /* vertical retrace end */
  2517.     vreout = vrsout + 2;
  2518. /* make sure the retrace fits into our adjusted display size */
  2519.     if (vreout > (ytotalout - 9))
  2520.         ytotalout = vreout + 9;
  2521. /* write out the vertical retrace end */
  2522.     outreg[V_RETRACE_END_INDEX].value &= ~0x0f;
  2523.     outreg[V_RETRACE_END_INDEX].value |= (vreout & 0x0f);
  2524. /* vertical blanking start */
  2525.     vblksout = ydispout + 1;
  2526. /* check it's legal */
  2527.     if(vblksout > vreout)
  2528.         vblksout = vreout;
  2529. /* save the overflow value */
  2530.     overflowout |= ((vblksout & 0x100) >> 0x05);
  2531.     maxscanout |= ((vblksout & 0x200) >> 0x04);
  2532. /* write the v blank value out */
  2533.     outreg[V_BLANKING_START_INDEX].value = (vblksout & 0xff);
  2534. /* vertical blanking end */
  2535.     vblkeout = vreout + 1;
  2536. /* make sure the blanking fits into our adjusted display size */
  2537.     if (vblkeout > (ytotalout - 9))
  2538.         ytotalout = vblkeout + 9;
  2539. /* write out the vertical blanking total */
  2540.     outreg[V_BLANKING_END_INDEX].value = (vblkeout & 0xff);
  2541. /* update our output overflow */
  2542.     overflowout |= ((ytotalout & 0x100) >> 0x08) | ((ytotalout & 0x200) >> 0x04);
  2543. /* write out the new vertical total */
  2544.     outreg[V_TOTAL_INDEX].value = (ytotalout & 0xff);
  2545.  
  2546. /* write out our over flows */
  2547.     outreg[OVERFLOW_INDEX].value = overflowout;
  2548. /* finally the max scan line */
  2549.     outreg[MAXIMUM_SCANLINE_INDEX].value = maxscanout;
  2550. /* and we're done */
  2551.     return outreg;
  2552.  
  2553. }
  2554.  
  2555. void center_mode(Register *pReg)
  2556. {
  2557.     int center;
  2558.     int hrt_start, hrt_end, hrt, hblnk_start, hblnk_end;
  2559.     int vrt_start, vrt_end, vert_total, vert_display, vblnk_start, vrt, vblnk_end;
  2560. /* check for empty array */
  2561.     if (!pReg)
  2562.         return;
  2563. /* vertical retrace width */
  2564.     vrt = 2;
  2565. /* check the clock speed, to work out the retrace width */
  2566.     if (pReg[CLOCK_INDEX].value == 0xe7)
  2567.         hrt = 11;
  2568.     else
  2569.         hrt = 10;
  2570. /* our center x tweak value */
  2571.     center = center_x;
  2572. /* check for double width scanline rather than half clock (15.75kHz modes) */
  2573.     if( pReg[H_TOTAL_INDEX].value > 0x96)
  2574.     {
  2575.         center<<=1;
  2576.         hrt<<=1;
  2577.     }
  2578. /* set the hz retrace */
  2579.     hrt_start = pReg[H_RETRACE_START_INDEX].value;
  2580.     hrt_start += center;
  2581. /* make sure it's legal */
  2582.     if (hrt_start <= pReg[H_DISPLAY_INDEX].value)
  2583.         hrt_start = pReg[H_DISPLAY_INDEX].value + 1;
  2584.     pReg[H_RETRACE_START_INDEX].value = hrt_start;
  2585. /* set hz retrace end */
  2586.     hrt_end = hrt_start + hrt;
  2587. /* make sure it's legal */
  2588.     if( hrt_end > pReg[H_TOTAL_INDEX].value)
  2589.         hrt_end = pReg[H_TOTAL_INDEX].value;
  2590.  
  2591. /* set the hz blanking */
  2592.     hblnk_start = pReg[H_DISPLAY_INDEX].value + 1;
  2593. /* make sure it's legal */
  2594.     if (hblnk_start > hrt_start)
  2595.         hblnk_start = pReg[H_RETRACE_START_INDEX].value;
  2596.  
  2597.     pReg[H_BLANKING_START_INDEX].value = hblnk_start;
  2598. /* the horizontal blanking end */
  2599.     hblnk_end = hrt_end + 2;
  2600. /* make sure it's legal */
  2601.     if( hblnk_end > pReg[H_TOTAL_INDEX].value)
  2602.         hblnk_end = pReg[H_TOTAL_INDEX].value;
  2603. /* write horizontal blanking - include 7th test bit (always 1) */
  2604.     pReg[H_BLANKING_END_INDEX].value = (hblnk_end & 0x1f) | 0x80;
  2605. /* include the 5th bit of the horizontal blanking in the horizontal retrace reg. */
  2606.     hrt_end = ((hrt_end & 0x1f) | ((hblnk_end & 0x20) << 2));
  2607.     pReg[H_RETRACE_END_INDEX].value = hrt_end;
  2608.  
  2609.  
  2610. /* get the vt retrace */
  2611.     vrt_start = pReg[V_RETRACE_START_INDEX].value | ((pReg[OVERFLOW_INDEX].value & 0x04) << 6) |
  2612.                 ((pReg[OVERFLOW_INDEX].value & 0x80) << 2);
  2613.  
  2614. /* set the new retrace start */
  2615.     vrt_start += center_y;
  2616. /* check it's legal, get the display line count */
  2617.     vert_display = (pReg[V_END_INDEX].value | ((pReg[OVERFLOW_INDEX].value & 0x02) << 7) |
  2618.                 ((pReg[OVERFLOW_INDEX].value & 0x40) << 3)) + 1;
  2619.  
  2620.     if (vrt_start < vert_display)
  2621.         vrt_start = vert_display;
  2622.  
  2623. /* and get the vertical line count */
  2624.     vert_total = pReg[V_TOTAL_INDEX].value | ((pReg[OVERFLOW_INDEX].value & 0x01) << 8) |
  2625.                 ((pReg[OVERFLOW_INDEX].value & 0x20) << 4);
  2626.  
  2627.  
  2628.  
  2629.     pReg[V_RETRACE_START_INDEX].value = (vrt_start & 0xff);
  2630.     pReg[OVERFLOW_INDEX].value &= ~0x84;
  2631.     pReg[OVERFLOW_INDEX].value |= ((vrt_start & 0x100) >> 6);
  2632.     pReg[OVERFLOW_INDEX].value |= ((vrt_start & 0x200) >> 2);
  2633.     vrt_end = vrt_start + vrt;
  2634.  
  2635.  
  2636.     if (vrt_end > vert_total)
  2637.         vrt_end = vert_total;
  2638.  
  2639. /* write retrace end, include CRT protection and IRQ2 bits */
  2640.     pReg[V_RETRACE_END_INDEX].value = (vrt_end  & 0x0f) | 0x80 | 0x20;
  2641.  
  2642. /* get the start of vt blanking */
  2643.     vblnk_start = vert_display + 1;
  2644. /* check it's legal */
  2645.     if (vblnk_start > vrt_start)
  2646.         vblnk_start = vrt_start;
  2647. /* and the end */
  2648.     vblnk_end = vrt_end + 2;
  2649. /* check it's legal */
  2650.     if (vblnk_end > vert_total)
  2651.         vblnk_end = vert_total;
  2652. /* set vblank start */
  2653.     pReg[V_BLANKING_START_INDEX].value = (vblnk_start & 0xff);
  2654. /* write out any overflows */
  2655.     pReg[OVERFLOW_INDEX].value &= ~0x08;
  2656.     pReg[OVERFLOW_INDEX].value |= ((vblnk_start & 0x100) >> 5);
  2657.     pReg[MAXIMUM_SCANLINE_INDEX].value &= ~0x20;
  2658.     pReg[MAXIMUM_SCANLINE_INDEX].value |= ((vblnk_start &0x200) >> 4);
  2659. /* set the vblank end */
  2660.     pReg[V_BLANKING_END_INDEX].value = (vblnk_end & 0xff);
  2661. }
  2662.  
  2663.